低レベルなヒトの覚え書き

●LSI C-86のエラー

2. 「NULL pointer assignment」(と見せかけて、本当はスタックオーバーフロー)


[実験 - その3]

スタックオーバーフローの原因になりがちなことでは、巨大な配列と双璧をなす(かもしれない)のが、関数の再帰呼び出しです。
ここでは、階乗の計算を行なうプログラム(リスト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」による終了となりました。

→トップ , →ひとつ上(lsic2)


R.2: 2006/08/01
Copyright (C) 2005,2006 A.Satoshi