_alloca() って知ってますか?
_alloca() は、メモリをスタックから動的に割り当てる関数です。関数を抜けると自動的に解放されます。
当然ながら、大量に割り当てようとするとスタックオーバーフローを起こします。
C# の stackalloc と似たような感じですが、こちらはスタックオーバーフローを含めたバッファオーバーランの検出を自動的に行ってくれるので結構安心して使えます。
_alloca() はスタックオーバーフローを起こしてしまう可能性があるため、_alloca() の解説にある通り _malloca()?を使うべきなのですが、こいつはヒープから割り当てられる可能性があるので、_freea() を明示的に呼び出してやる必要があり、非常にめんどいです。
?
もっと安心して _alloca() みたいな機能が使えないかな、ということで ATL の出番です。
atlalloc.h には _ATL_SAFE_ALLOCA() というマクロがあり、これを使うと _malloca() みたいな動作(小さい値ならスタックから、大きい値ならヒープから確保)をしますが、解放を明示的に行う必要はありません。
ただし、_ATL_SAFE_ALLOCA() を使用する前に USES_ATL_SAFE_ALLOCA という文を記述しておく必要があります。
void foo()
{
// これを宣言しておく必要がある。
USES_ATL_SAFE_ALLOCA;
// 1MB のメモリをスタックから確保する?
void* p = _ATL_SAFE_ALLOCA(1 * 1024 * 1024, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
// _ATL_SAFE_ALLOCA_DEF_THRESHOLD より大きい値なので、実際はヒープから確保される
// p を使ってほげほげする
...
// 解放はしなくて良い
return;
}
_ATL_SAFE_ALLOCA の第2引数はスタックから確保するかヒープから確保するかの境界線で、この値以下の要求であればスタックから確保され、そうでない場合はヒープから確保されます。あとそれから、この値以下であっても、それを確保したらスタックオーバーフローを起こしてしまう場合にもヒープから確保します。
_ATL_SAFE_ALLOCA_DEF_THRESHOLD というのは ATL が設定したデフォルト値です。現在は 1024 と定義されているようです。
?
これを使えば、スタックオーバーフローの危険性が少なく、しかも利便性を損なわず _alloca() みたいな機能が使えるので、_alloca() や _malloca() を使うぐらいであれば、是非こちらを使ってみましょう。