3

次のコードがデバッグ ビルドでは正しく動作するが、リリースでは正しく動作しないことを発見しました。

enum FileFormatDetection
{
    Binary,
    ASCII,
    Auto
};

FileFormatDetection detection_mode = (FileFormatDetection)ReadIntKey(NULL, KEY_ALL, "FIL_ASCIIORBINARY", -1); // Assigns -1, as confirmed by debug output
if (detection_mode < 0 || detection_mode > 2)
{
    // Not a valid value, so set to default:
    detection_mode = Auto;
}

各ビルドのデバッグ出力で、値が -1 であることが確認されました。デバッグ ビルドでは、値 -1 により if-branch に入りました。リリースでは、そうではありませんでした。

次のように、detection_mode を int にキャストしようとしました。

if ((int)detection_mode < 0 || (int)detection_mode > 2)

と:

if (int(detection_mode) < 0 || int(detection_mode) > 2)

しかし、どちらも違いはありません。

これを機能させる唯一の方法は、enum 変数を整数のスタック変数にキャストし、次のことをテストすることでした。

int detection_int = (int)detection_mode;
if (detection_int < 0 || detection_int > 2)
{
    ...

これで、予想どおり、if 分岐が入力されました。

なぜこれが必要だったのか理解できません - 元のコード (または少なくともキャストの一時的なテスト) が機能するはずだったと今でも思います。なぜそうしなかったのか誰か説明できますか?

4

2 に答える 2

10

問題は、列挙子の1つではない値を列挙に割り当てているため、キャストが未定義の動作を引き起こしていることです。

リリース モードでコンパイルすると、オプティマイザーは次の式を認識します。

if (detection_mode < 0 || detection_mode > 2)

の型がdetection_modeisFileFormatDetectionであることを知っており、その特定の列挙型のすべての有効な値が範囲内にあることを知っているため、if ステートメントは決してtrue(少なくとも適切に定義されたプログラムでは) 存在しないため、if完全に削除されます。

同じ理由が適用されるため、 へのキャストは役に立ちません: キャスト前の値 (ここでも適切に定義されたプログラム内) は範囲内にあるintため、オプティマイザーは を削除します。どちらの場合も比較のために列挙型が変換されるため、キャストが明示的であるかどうかは実際には問題ではないことに注意することが重要です。if[0..2]ifint

値をに格納するとint、すべてが変更されます。intその範囲外の値がかなりあるため、比較を実行する必要があります。-1 また、この変更により、は有効なであるため、プログラムが適切に定義されることに注意してくださいint。これは実際にやるべきことです: 値を として取得intし、列挙型に変換できる場合にのみ変換を実行します。

于 2012-07-16T17:22:21.403 に答える
6

変数のdetection_modeタイプFileFormatDetectionは、であるため、(合法的に)範囲0..2の値のみを含めることができます。それ以外は未定義の動作です。あなたの場合、明らかに、オプティマイザーはこれを認識しており、テストをゼロ未満に抑制しています。

あなたがしなければならないことは、を読んで、範囲チェックのintにのみ変換すること です:FileFormatDetection

int raw_detection_mode = ReadIntKey(...);
if ( raw_detection_mode <= 0 || raw_detection_mode > 2 ) {
    raw_detection_mode = Auto;
}
FileFormatDetection detection_mode =
    static_cast<FileFormatDetection>( raw_detection_mode );
于 2012-07-16T17:23:54.180 に答える