ヒープの代わりに stack にメモリを割り当てる方法はありますか?これに関する良い本を見つけることができません。
alloca()
(__alloca()
または _malloca()
と呼ばれることもあります)を使用しますが、 非常に注意してくださいabout —スコープ外に出たときではなく、関数を離れたときにメモリを解放するため、ループ内で使用するとすぐに爆発します。
たとえば、次のような関数がある場合
_int foo( int nDataSize, int iterations )
{
for ( int i = 0; i < iterations ; ++i )
{
char *bytes = alloca( nDataSize );
// the memory above IS NOT FREED when we pass the brace below!
}
return 0;
} // alloca() memory only gets freed here
_
次に、alloca()は、ループを通るたびにadditionalnDataSizeバイトを割り当てます。 alloca()バイトは、関数から戻るまで解放されません。したがって、nDataSize
が1024でiterations
が8の場合、戻る前に8キロバイトを割り当てます。 nDataSize
= 65536およびiterations
= 32768がある場合、合計65536×32768 = 2,147,483,648バイトを割り当てます。ほとんど確実にスタックを破壊し、クラッシュを引き起こします。
anecdote:バッファの終わりを超えて書き込むと、特にバッファを別の関数に渡し、そのサブ関数がバッファの長さについての間違った考え。 以前はかなり面白いバグを修正しました GPUメモリに送信する前にTrueTypeフォントグリフをレンダリングするための一時ストレージを作成するためにalloca()
を使用していました。フォントライブラリは、グリフのサイズを計算するときにスウェーデン語のÅ文字の発音区別符号を考慮していなかったため、レンダリング前にグリフを格納するためにnバイトを割り当て、実際にレンダリングn+ 128バイト。余分な128バイトがコールスタックに書き込まれ、リターンアドレスが上書きされ、非常に苦痛な非決定的なクラッシュが発生しました。
これはC++でタグ付けされているため、通常は必要なオブジェクトを正しいスコープで宣言するだけです。これらはスタックに割り当てられ、スコープの終了時に解放されることが保証されています。これは [〜#〜] raii [〜#〜] であり、Cに対するC++の重要な利点です。malloc
sまたはnew
sなし、特にalloca
s、必須。
ローカルchar[1024]
または任意のバイト数(ポイントまで)を宣言し、スタック上のこのメモリブロックへのポインターのローカルアドレスを取得できます。正確に動的ではありませんが、必要に応じて、このメモリを独自のメモリマネージャでラップできます。
関数_allocaを使用して、スタックメモリに可変長スペースを動的に割り当てることができます。この関数は、プログラムスタックからメモリを割り当てます。割り当てられるバイト数を取得し、malloc呼び出しと同様に割り当てられたスペースにvoid *を返します。この割り当てられたメモリは、関数の終了時に自動的に解放されます。
したがって、明示的に解放する必要はありません。スタックオーバーフロー例外が発生する可能性があるため、ここで割り当てサイズについて留意する必要があります。このような呼び出しには、スタックオーバーフロー例外処理を使用できます。スタックオーバーフロー例外の場合、
_resetstkoflw()
を使用して元に戻すことができます。したがって、
_alloca
を使用した新しいコードは次のようになります。int NewFunctionA() { char* pszLineBuffer = (char*) _alloca(1024*sizeof(char)); ….. // Program logic …. //no need to free szLineBuffer return 1; }
見る - _malloca
。
C++が(非静的な)const
値の配列境界の使用を許可している場合は、より簡単になります。
今のところ、私が知っている最良の方法は再帰を経由することです。実行できるあらゆる種類の巧妙なトリックがありますが、私が知っている最も簡単な方法は、ルーチンに固定サイズの配列を宣言させ、その配列に値を入れて操作することです。完了すると、終了するためにより多くのスペースが必要な場合、自身を呼び出します。
[〜#〜] bde [〜#〜] C++ライブラリを使用できます。
const int BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
bdlma::BufferedSequentialAllocator allocator(buffer, BUFFER_SIZE);
bsl::vector<int> dataVector(&allocator);
dataVector.resize(50);
BDEは、コンテナのタイプを変更せずにポリモーフィックアロケータを使用できるbsl :: vectorなどのコレクションとともに、包括的なアロケータオプションを提供します。
次のことも検討してください。