データがメモリへどのようにアロケーションされるかは OS や libc およびコンパイラに依存する。
Linux 2.6 の場合、どうもユーザ自身が limit でスタックの使用量を制限しないと、スタックもヒープも拡張し放題で、最終的に衝突してしまうことを許しているみたい。
Heap / stack overlap
警告: Linux x86 では、メモリ使用率の設定を高くし過ぎないように注意してください。glibc はプロセスヒープがスレッドスタックよりも大きくなることを許可しており、その場合にサーバがクラッシュします。
ヒープが成長する時にスタックに衝突してしまった場合には malloc() が NULL を返したりすることで検出できるみたいだが、逆にスタックの成長を引き起こす関数呼び出しがヒープに衝突してしまっても、特にチェックしていないという雰囲気。
ちなみにこれを再現したプログラムはヒープを G 単位まで確保し、その後で再帰呼び出しを数万回くらい繰り返すような代物である。
見事に再帰呼び出し中のとある局所変数がヒープに置いてあったリストを破壊して、その後にそのリストのリンクをたどっている途中で SIGSEGV を発生させてくれました。最初はリストの実装が悪いのかかなり悩んじゃいました。
...というような情報を日本語で探してたんだけど、見当たらなかったのでここにメモしておくことにする。