実際の質問については質問部分にジャンプしてください。未定義の動作の興味深い実際の例では、読書を保つ:)配列の範囲外要素の値 - 実行ごとに変更するか、同じままにする必要がありますか?
この列挙がありました:
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
};
を次にありましたループはarr
のarrayCount
要素をファイルに入れます。これはユニットテスト用の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です...私は混乱しています。 ところで、同じプロジェクトをビルドすると、範囲外要素は、実行ごとに常に異なる値を持ちます。これを説明してもらえますか?ありがとう。
「プリプロセッサを使用しないでください」;-) –
これは、InvalidValueが定数であった場合に、定数をマクロに優先して使用することをお勧めします。これはコンパイル時に捕捉されます。 enum:enum_countに余分な値を追加することで、enumの要素の数を取得できるようになります(0から始まり、enum値の値を手動で設定しないと仮定します)。それは哨戒値として。 –
@ Kerrek @ David:確かに、私はその "コード"を書いた人ではありませんでした:) –