スタックオーバーフローの原因になりがちなことでは、巨大な配列と双璧をなす(かもしれない)のが、関数の再帰呼び出しです。
ここでは、階乗の計算を行なうプログラム(リスト6)を材料として、スタックがあふれていく様子を観察することにしました。
なお、実験1との対応を考慮して、この実験でもコンパイルの条件が異なる4種類の実行ファイルを使用しました。
[リスト6] | /* intlibをリンクした場合、階乗の計算結果は正しく表示されない */ | #include<stdio.h> | #include<malloc.h> | double sub(int A); | int main() { | int X; | for (X=1; X<200; X++) { | printf("%d: %g\n", X, sub(X)); | } | return 0; | } | double sub(int A) { | if (A>1) { | return A*sub(A-1); | } | else { | printf("s(%d)\n", stackavail()); | return 1; | } | }
まず、特別なオプションなしでコンパイルした場合、A=145(スタック残量156)、A=146(同140)までは正常、A=147(同0124)で怪しくなり、A=148でフリーズ。
スタックオーバーフローの検査を行なう「-h」オプションを指定した場合も、A=145(同152)、A=146(同136)までは正常、A=147(同20)で怪しげ、A=148でフリーズ。
intlibをリンクした場合は多少様子が違っていて、A=153(同28)、A=154(同12)のあと、A=155からA=168まではスタック残量ゼロの表示が続き、A=168に至って「Floating exception: Overflow」と「NULL pointer assignment」という2つのエラーメッセージとともに終了となりました。
「-h」オプションとintlibを同時に指定した場合は、A=153(同24)、A=154(同8)ときて、A=155で「stack overflow」による終了となりました。