1

実際の質問については質問部分にジャンプしてください。未定義の動作の興味深い実際の例では、読書を保つ:)配列の範囲外要素の値 - 実行ごとに変更するか、同じままにする必要がありますか?

この列挙がありました:

struct EnumStruct 
{ 
    enum Enum 
    { 
     val0 = 0, 
     val1, 
     val2, 
     val3, 
     val4 
    }; 
}; 

は、いくつかの機能では、我々は、この持っていた:

const int arrayCount = 6; 
int arr[] = { 
     EnumStruct::val0, 
     EnumStruct::val1, 
     EnumStruct::val2, 
     EnumStruct::val3, 
     EnumStruct::val4 
     InvalidValue 
     };  

を次にありましたループはarrarrayCount要素をファイルに入れます。これはユニットテスト用のPrepare()ルーチンでした。ユニットテストではファイル内にInvalidValueが存在するかどうかを確認する予定でした。私は単体テストが失敗したという欠陥を割り当てられました。それは私のマシンで完璧に働いた。数時間のデバッグの後、私はInvalidValueが実際に#define dであり、-1であり、val4の後にカンマがないことに気づいた。あなたは、そのコードを書いた人の住所で私の口から出された誓約を想像することしかできません(実際には3年以上完璧に働いていました)。

ここから分かるように、配列は実際には0, 1, 2, 3, 3という5つの値で構成されていますが、ループは6番目の要素もファイルに書き出しますが、これはもちろん未定義の動作です。現在、技術的にはですが、MSVCのクラッシュは発生しません。そのメモリ位置にあるゴミを書き込みます。問題は、ごみが0, 1, 2, 3, or 4以外であれば、単体テストが成功するということです。

質問:UTのが構築される前に、UTのの.vcprojファイルが何らかの理由でパッチが適用されることが表示されます。私は彼らがどのようにそれを行うのかわかりませんが、その範囲外の配列要素は常に0です。プログラム実行前に仮想メモリ全体が0に設定されているようです。どんなプロジェクト設定ですか?または私は物事を想像していますか? 私は、配列の範囲外に座っていることが運が正しければ、複数回実行すると運がうまくいかないと思いますか?しかし、それは常に0です...私は混乱しています。 ところで、同じプロジェクトをビルドすると、範囲外要素は、実行ごとに常に異なる値を持ちます。これを説明してもらえますか?ありがとう。

+0

「プリプロセッサを使用しないでください」;-) –

+1

これは、InvalidValueが定数であった場合に、定数をマクロに優先して使用することをお勧めします。これはコンパイル時に捕捉されます。 enum:enum_countに余分な値を追加することで、enumの要素の数を取得できるようになります(0から始まり、enum値の値を手動で設定しないと仮定します)。それは哨戒値として。 –

+0

@ Kerrek @ David:確かに、私はその "コード"を書いた人ではありませんでした:) –

答えて

0

実際の質問には、最初はいつもメモリが0ですか?まあ、それは依存するかもしれません。一般に、OSがあなたにメモリのページを提供するとき、それは(セキュリティ手段として、他のプロセスがそのメモリに持っていた値を読むことができないように)クリアされるので、多くの場合、初期化されていないは、自分のプロセスでメモリが再利用されるまで、0に似ています。

これに影響を与えるコンパイラフラグもあります。初期化されていないメモリの問題を検出するために、OSから割り当てられたプログラムをプログラムに渡す前に、デバッグビルドがメモリにパターンを書き込むことがあります(解放されたメモリへのアクセスを検出するために)何が起こったのかを簡単に特定できます(値が0xDEADBEEFであることがデバッガに表示されている場合は、プログラムによってメモリが解放されていることがわかります)。

0

あなたが言うように、それは未定義なので、実装者は自由に自由に行うことができます。私はVisual C++については全く話すことができませんが、デバッグビルドを実行するときにメモリをゼロにするなど、無効なポインタデリファレンスのようなものがフォルトのサイトで失敗するようなことを行う他の製品について認識しています。 Microsoftも同様のことをやっている可能性があります。

+0

実際にリリースビルドです –