すべての用途に対応するのに十分な大きさの固定サイズのバッファーをスタックに常に割り当てることができるのに、なぜalloca()を使用したいのでしょうか。これは修辞的な質問ではありません...
6 に答える
バッファのサイズが実行時に変化する場合、またはたまにしか必要ない場合に役立つ可能性があります。これにより、各呼び出しで固定サイズのバッファよりも全体的に使用されるスタックスペースが少なくなります。特に、関数がスタックの上位または再帰的である場合。
決して-C++の一部ではなく、Cでは役に立ちません。ただし、「スタックに静的バッファ」を割り当てることはできません。静的バッファは、スタックではなくコンパイル時に割り当てられます。
alloca()のポイントは、もちろん、サイズが固定されておらず、スタック上にあり、関数が終了すると自動的に解放されることです。C ++とCはどちらも、これを処理するためのより優れたメカニズムを備えています。
コンパイル時に必要になる可能性のある最大サイズを知る方法がない場合は、これを使用することをお勧めします。
あなたがすべきかどうかは別の質問です-それは標準ではなく、それがスタックオーバーフローを引き起こす可能性があるかどうかを判断する方法はありません。
どの場合にalloca()は役に立ちますか?
allocaが使用されているのを見たのは、OpenDynamicsEngineだけでした。AFAIKは、巨大な行列を割り当てていました(したがって、コンパイルされたプログラムには100MBのスタックが必要になる可能性があります)。これは、関数が戻ると自動的に解放されます(私にはスマートポインターのリップオフのように見えます)。これはかなり前のことです。
おそらくnew/mallocよりもはるかに高速でしたが、それでも悪い考えだったと思います。シーンが複雑になりすぎて処理できなくなった場合、RAMプログラムを丁寧に使い果たす代わりに、スタックオーバーフロー(つまり誤解を招く)でクラッシュする可能性があります。良い動作ではありません。IMO、特に物理エンジンの場合、誰かが数千のレンガをシーンに投げ込み、それらがすべて一度に衝突したときに何が起こるかを簡単に確認できます。さらに、スタックサイズを手動で設定する必要がありました。つまり、RAMが多いシステムでは、プログラムはスタックサイズによって制限されます。
すべての用途に適合するのに十分な大きさのスタック上の固定サイズのバッファー?これは修辞的な質問ではありません...
すべての用途に固定サイズのバッファが必要な場合は、静的/グローバル変数に入れるか、ヒープメモリを使用することもできます。
このalloca()
関数は事実上必要ありません。メモリ割り当ての目的で、 C(またはC ++の可能性のコレクションの1つ)でmalloc()
/free()
を使用して、ほぼ同じ実用的な効果を実現できます。これには、スタックサイズが小さいほどうまく対処できるという利点があります。
しかし、私は[1]それの1つの合法的な使用を見てきました:Windowsでの潜在的なスタックオーバーフローを検出するため。(アクセスしたいスロップスペースの量の)割り当てが失敗した場合、あなたは外出していましたが、正常に回復するのに十分なスペースがありました。クラッシュしないように__try
/でラップされており、gccによるトラブルを回避するために追加のアセンブラートリックが必要でした。__except
私が言ったように、ハック。alloca()
しかし、私が今まで見た中で唯一の有効な使用法である賢いもの。
しかし、そうしないでください。そのようなゲームを必要としないようにコードを書く方が良いです。
[1]それはTcl8.4(そしておそらく以前のバージョンのTcl)にありました。それ以降のバージョンでは削除されました。それ以降のバージョンでは、それが厄介で、非常にトリッキーで、非常に厄介だったため、削除されました。8.6は、そのようなファンキーさの代わりに、実行エンジンのスタックレス実装を使用します。
確実に(またはC ++、または別のメモリアロケータで)使用できない場合、またはまったく使用できない場合は、使用するのが妥当alloca()
かもしれませんが、スタックに使用可能なスペースがもっとあると想定できます。つまり、他に何もできない場合です。 。malloc()
new
たとえば、glibc
's segfault.cには、次のものがあります。
/* This function is called when a segmentation fault is caught. The system
is in an unstable state now. This means especially that malloc() might
not work anymore. */
static void
catch_segfault (int signal, SIGCONTEXT ctx)
{
void **arr;
/* ... */
/* Get the backtrace. */
arr = alloca (256 * sizeof (void *));
/* ... */
}