1

私はこのようなCプログラムを持っています。

int indexLength;
char *args[1024];
while(args[indexLength])
     indexLength++;

職場のコンピューターでプログラムを実行すると、while ループの行で segfault が発生し、indexLength はばかげた任意の値を取ります。しかし、自宅の Linux マシンでプログラムを実行すると、セグメンテーション違反は発生せず、プログラムは正常に実行されます。

私が考えることができる2台のマシンの唯一の違いは、職場のマシンにはgcc4.7 redhatバージョンがあり、Fedora OSを実行しており、自宅のマシンにはppaリポジトリからダウンロードされたgcc4.7があり、ubuntu OSを実行していることです。しかし、それが唯一の違いだとは思いません! それは何でしょうか?

編集:申し訳ありませんが、言及するのを忘れていました。indexLength = 0を初期化すると、職場のコンピューターでセグメンテーション違反がなくなりました..

4

2 に答える 2

5

初期化されていないメモリからの読み取りは未定義の動作です。変数はデフォルトでは初期化されないため、indexLength割り当てるまでは任意の値を取ることができます。動作が定義されていないため、プログラムは一部のマシンで実行され、他のマシンではクラッシュする可能性があります。

さらに、indexLengthをゼロに初期化しても、初期化されないままになるため、未定義の動作は修正されませんargs。これは、プログラムが配列の終わりに到達しても停止せず、割り当てられた領域の終わりを超えた値にアクセスする可能性があることを意味します。もちろん、これを行うには、1024 項目の配列内のすべての値が非ゼロでなければならないため、配列の最後に到達する前に停止する方が有利です。ただし、この未定義の動作を修正するには、値にアクセスする前にインデックスを確認する必要があります。

于 2013-05-22T12:52:18.317 に答える
3

あなたのコードは未定義の動作を呼び出します

  • args初期化されていないため、各要素には予測できない値が含まれています。おそらく、スタックの次の 4k で NULL ポインターを見つけ、ループを終了します。多分あなたはそうせず、配列の終わりを超えて読むでしょう
  • indexLength初期化されていないので、すぐに配列の末尾を超えて読み取ることができます
  • の最後を超えて読んだ場合の影響argsも予測できません。これには、プロセスの読み取り可能なメモリの制限に達する前にゼロ ワードが見つからない場合など、クラッシュする可能性が含まれます。

最初の外観にもかかわらず、設定indexLength=0によって実際にコードが安全になるわけではありません。まだ初期化されていないメモリを読み取っているため、内部で NULL 要素を見つけることに依存していますargs。あなたがこれを見つけることを保証する方法はありません。配列の最後に到達する前にループが終了しない場合は、未定義の動作に戻るため、それ以上の反復でプログラムがクラッシュする可能性があります。

于 2013-05-22T12:52:24.553 に答える