C言語で動的なサイズのメモリ確保が必要となれば、典型的にはmalloc
とfree
の出番ですが、alloca
というものもあります。
C言語での変数の寿命
オブジェクト指向な言語の多くでは、ガベージコレクタが入っているので、「オブジェクトの寿命」≒「オブジェクトへの参照が存在する間」ということになります。これに対して、C言語(やC++)では、ガベージコレクタのような高度な仕組みはないので、変数の寿命は次の2つのどちらかになります。そして、C11で加わった可変長配列を別として、配列を確保するときもサイズは固定のしか取れません。
- 自動変数…スコープに入ったところで変数が用意され、スコープを抜けたところで解放される
- 静的変数・外部変数…プログラムの開始から終了まで存在し続ける
これらに当てはまらない操作をしようと思えば、ライブラリ関数を使ってポインタ経由で使うほかありません。
allocaとは
ふつう、C言語で動的確保をしようと思えばmalloc
~free
の流れですが、標準関数ではないものの多くの環境にalloca
、あるいは_alloca
という関数があります。この関数の特徴としては、「メモリ領域をスタックに取る」ということがあります。そのため、
- 使い終わった後の
free
の必要がない(というより、してはならない) - スコープを抜ければ自動で解放される
- 返り値としてこのメモリ領域へのポインタを返してはいけない
- オーバーヘッドが少ない
- アセンブラで埋め込み展開されるような環境もある(
alloca
関数へのポインタを取れない) - 巨大な領域を取るとスタックオーバーフローで死ぬ
というような特徴があります。
この前使った場面では、実行時までサイズが決まらない配列を確保する必要があったのですが、その配列自体は外からアクセスする必要がなく、そして処理全体に対するmalloc
のオーバーヘッドがかなりのものになる、という状況だったので、「必要な長さが小さな時にはalloca
に切り替える」ようにしたところ、3割程度高速化した、ということがありました。