16章_奇妙な問題



16.3:
プログラムが走る前にクラッシュする(デバッガーを使って一行づつ ステップ実行で追うとmain()の最初の行を実行する前に死んでしまう)。

A:

このプログラムは、非常に大きな(1キロバイトかそれ以上の)ローカ ルな配列を持っているはずだ。多くのシステムではスタックの大きさ は固定だし、(Unixのように)動的にスタックを自動的に確保するシス テムでもスタックのサイズが突然巨大になると、混乱する場合がある。 大きな配列を使うときはstaticと宣言したほうがいい(もちろん再帰 呼び出しするたびに新しい配列が必要な場合は除く。こういう場合は malloc()を使って動的に確保する。質問1.31を参照のこと)。

(質問11.12, 16.4, 16.5, 18.4も参照のこと)


16.4:
このプログラムは正しく動いているように見えるけれど、main()から 抜けるところで、つまりmain()の最後の文の後で、クラッシュする。 なにがこんなことを引き起こすのか。

A:

main()のプロトタイプ宣言のおかしくないかとか(質問2.18, 10.9参 照)、setbuf()とかsetvbuf()にローカルのバッファを渡してないかと か、atexit()に登録した後片付けの関数に間違いはないかを調べる。 質問7.511.16も参照のこと。

References:
CT&P Sec. 5.3 pp. 72-3.


16.5:
このプログラム、あるマシンではうまく走るのに、別のマシンだと変 な結果を返す。もっと変なことに、デバッグ用の出力を付けたり外し たりすると症状が違ってくる。

A:

おかしくなる可能性のあるものはたくさんある。以下に可能性の高い ものをいくつか示す。

初期化してないローカル変数(質問7.1参照)

整数のオーバーフロー、特に16ビットマシンで、とりわけ a * b / cのような計算の中間結果の桁溢れ(質問3.14も参照 のこと)

未定義の評価の順序(質問3.1から3.4も参照のこと)

external関数の宣言のし忘れ、特にint以外を返す関数で(質 問1.25と14.2参照)

ヌルポインターの間接参照(5章参照)

誤ったmalloc/freeの使い方。mallocしたメモリが全部0に なってるとかfreeした領域がまだ使えると思い込んだり、同 じものを2回freeすること(質問7.207.19を参照のこと)

ポインターの問題全般(質問16.8も参照のこと)

printf()の書式と実引数の不一致、特にlongの整数を%dを使っ て出力しようとする(質問12.9も参照)

malloc(256 * 256 * sizeof(double))を実行しようとする。 特にメモリの量が限られているマシンで(質問7.1619.23 も参照のこと)

配列の境界の問題。特に小さな一時的バッファで、おそらく sprintf()を使って文字列を構築するのに使う(質問7.112.21も参照)

typedefと実際のデータ型の対応の誤った思い込み。とりわ けsize_t

浮動小数点の問題(質問14.114.4を参照)

対象となる具体的なシステムで コードの生成されかたを決 め付けて、こういう使いかたを考え付くとは俺って頭がいい なと思っていることはなんでも

関数プロトタイプを適切に使うことで、これらの問題のかなりの部分 を捕まえることができる。lintを使えばもっと多くの問題を捕まえる ことができる。質問16.3, 16.4, 18.4も参照のこと。


16.6:
なぜ以下のコードはクラッシュするのか。

	char *p = "hello, world!";
	p[0] = 'H';

A:

文字列定数は、(ようするに)配列の初期化指定子として使われるとき を除いては、必ずしも変更可能ではない。以下の方法を試すこと。

	char a[] = "hello, world!";

質問1.32も参照のこと。

References:
ANSI Sec. 3.1.4; ISO Sec. 6.1.4; H&S Sec. 2.7.4 pp. 31-2.


16.8:
「セグメンテーション違反(Segmentation violation)」とか「バスエ ラー(Bus error)」は何を意味するのか。

A:

これらは一般に、アクセスすべきでない記憶領域にプログラムがアク セスしようとしたことを意味している。きっとポインターの使い方が 適切でなかったからに違いない。考えられる原因としては以下のもの が考えられる。

ヌルポインターの誤った使い方(質問5.2, 5.20も参照)。初期化され ていないポインター/境界の合ってないポインター/その他適切でない 確保のされかたのポインター(質問7.17.2参照)。mallocした領域が 壊れた(質問7.19参照)。関数引数の不一致、特にポインターが絡んだ 場合、2つ考えられるのはscanf()(質問12.12参照)とfprintf()(最初 のFILE *の引数を渡されていることを確認すること)。

質問16.316.4も参照のこと。

目次へ戻る