スタックからのメモリ確保の標準化

江添亮
仕事: C++エヴァンジェリスト(ドワンゴ)
http://cpplover.blogspot.jp/
boostcpp@gmail.com
GitHub: EzoeRyou

Themes

Sky - Beige - Simple - Serif - Night - Default

Transition Styles

Cube - Page - Concave - Zoom - Linear - Fade - None - Default

C++のメモリの種類

  • 静的ストレージ
  • スレッドストレージ
  • 自動ストレージ
  • 動的ストレージ

静的ストレージ

  • 名前空間スコープの変数
  • static指定されたクラススコープ
  • 関数のブロックスコープの変数など

よくある実装例

プログラムファイルに格納

例:ELFにおける.dataや.bss

スレッドストレージ

thread_local指定された変数

よくある実装例

プログラムファイルに格納

例:ELFにおける.tdataや.tbss

自動ストレージ

いわゆるローカル変数

よくある実装例

スタックから確保

動的ストレージ

実行時に動的なサイズのストレージを確保できる

よくある実装例

ヒープと呼ばれる管理されたメモリ空間から確保

スタック

よくある実装

確保済みの連続したメモリとスタックポインターの増減で実装

確保、解放がとても速い

ヒープ

実装は様々

大きな連続したメモリ領域を管理して確保

一般的に、スタックより遅い

要望

速いスタックから動的にストレージを確保したい

小さなサイズのメモリ領域を

極めて短時間確保したい

用途:ゲーム、音声動画圧縮のエンコーダー/デコーダー、数値計算

alloca

template < typename T >
void f()
{
    void * p = alloca( sizeof(T) ) ;
    T * t = new(p) T() ;

    T->~T() ;
}

allocaの問題点

  • 型安全ではない
  • コンストラクター、デストラクターの面倒を見てくれない

動的ストレージの問題点

遅い

極小サイズならば

それぞれのサイズごとに分けたメモリ領域から

割り当てるテクニックもある

でも遅い

スタックを使わせろ

実行時サイズ配列

C++14に追加される予定だった

void f( std::size_t size )
{
    char a[ size ] ;
}

dynarray

C++14に追加される予定だった

void f( std::size_t size )
{
    std::dynarray<char> a( size ) ;
}

スイスのせいでTS落ち

コメント

C++14はマイナー新機能を含むバグ修正リリースが目的であったはずだ

提案する変更

規格の品質に悪影響を及ぼす新機能をすべて取り除け

悲しい

optionalさんも巻き添えになった

実行時サイズ配列の問題点

データメンバーとしては使えず、直接使わなければならない

実行時サイズ配列を使って

dynarrayを実装することは出来ない

dynarrayの問題点

データメンバーなど、スタック確保できないところで使うと

自動的に動的ストレージから確保される

スタックから確保したければ、直接使わなければならない

直接使うことの問題点

Abstractionができない

つまり、クラスでラップして使えない

Abstraction可能な提案

N3875

実行時サイズ配列をデータメンバーとして使える提案

struct Foo
{
    Foo( std::size_t size ) : v[size]{}
    { }

    char v[] ;
} ;

制約

実行時サイズ配列をデータメンバーとして持つクラスは

自動ストレージ上にしか構築できない

大前提崩壊

C++では、型はどのストレージ上にも構築できる

N3875提案が採用されれば、もはや成り立たない

dynarray To the Rescue!

dynarrayならば、どのストレージ上にも構築できる

実装にコンパイラーマジックが必要

絶対にスタックに確保されて欲しい需要には答えられない

そもそも

C++では、オブジェクトは明示的に破棄できる

C++では、オブジェクトは明示的に構築できる

お分かりか?

// ネストした確保
void f( std::dynarray<int> & r )
{
    r.~dynarray() ; // 破棄
    // 別のサイズで再確保
    new(r) std::dynarray<int>(2) ;
}

int main()
{
    std::dynarray<int> a(1) ;
    f( a ) ;
}

大前提崩壊

既存のC++では、これは当然できる

しかし、スタック確保の特性を考えると、できない

例外は作りたくない

ネストされたスタック確保の標準化

スタック確保を標準化するにあたって必要

まだ何も提案されていない

参考文献

ドワンゴ広告

ドワンゴに入社した直後、@ignis_fatuusからtweetが来た

ドワンゴ広告

札幌か

まあ

その頃には給料も入っているだろうし

行けるだろう

ドワンゴ広告

しかし

C++の啓蒙なら

仕事のうちではないか

ドワンゴ広告

江添「Boost勉強会行きたいんですけど旅費だして」
上司「じゃあ、出張ってことで」
上司「航空券とホテル、手配しといたよ」

謎の出張目的

Boost.勉強会 #15 札幌 に発表者として参加することで、ドワンゴのC++に対する取り 組みをアピールする狙いがある。

また、懇親会にも参加することで、C++エンジニアの中途採用につなげる狙いもある。

勉強会に呼んでくれ

宣伝になれば全国どこにでも行ける

ドワンゴ広告

このスライド資料はドワンゴ勤務中に書かれた。

ドワンゴは本物のC++プログラマーを募集しています。

http://info.dwango.co.jp/recruit/"