0

次のプログラムがあるとします。

using System;

namespace VS2012TestApp
{
    class Program
    {
        [Flags]
        public enum IoStatus : byte
        {
            ControlStore = (byte)128,
            Control = (byte)64,
            LogicalState = (byte)32,
            PhysicalState = (byte)16,
            NewEdge = (byte)4,
            Overload = (byte)2,
            NoLoad = (byte)1,
            None = (byte)0,
            Notify = (byte)8,
        }

        private static IoStatus Status = IoStatus.LogicalState;

        static void Main(string[] args)
        {
            Process(IoStatus.LogicalState | IoStatus.Overload, IoStatus.None);
        }

        private static void Process(IoStatus bitsSet, IoStatus bitsCleared)
        {
            bitsSet |= Status;
            bitsCleared |= ~Status;

            // Console.WriteLine("set {0}, clear {1}", bitsSet, bitsCleared);

            bitsSet &= ~(IoStatus.LogicalState | IoStatus.PhysicalState);
            bitsCleared &= ~(IoStatus.LogicalState | IoStatus.PhysicalState);

            Console.WriteLine("set {0}, clear {1}", bitsSet, bitsCleared);
        }
    }
}

デバッグ モードの Win7 x64 ビットの VS2012 (アップデート 3) では、次のようになります。

オーバーロードの設定、NoLoad のクリア、オーバーロード、NewEdge、Notify、Control、ControlStore

これは私が期待するものです。

リリース モード (最適化がオンの場合とオフの場合):

過負荷を設定し、なしをクリアします

これは間違っています。

ターゲット プラットフォームの AnyCPU または x86 は、どちらも同じ出力になります。このコードは、VS2008 のデバッグおよびリリース モードで正常に動作します。VS2010 は試していません。

編集:リリースモードでデバッガーで実行すると、正しい動作が生成されます。

次のいずれかの方法で修正できます。

  1. (現在コメントアウトされている)の挿入Console.WriteLine()
  2. enumtoのバッキング タイプの変更int
  3. のコードを次のように変更しますProcess

    private static void Process(IoStatus bitsSet, IoStatus bitsCleared)
    {
         bitsSet = (bitsSet | Status) & ~(IoStatus.LogicalState | IoStatus.PhysicalState);
         bitsCleared = (bitsCleared | ~Status) & ~(IoStatus.LogicalState | IoStatus.PhysicalState);
    
         Console.WriteLine("Set {0}, Clear {1}", bitsSet, bitsCleared);
     }
    

問題は、意図しない方法で列挙型を使用していて、単に「未定義の動作」に遭遇したのか、それともコンパイラ/ジッターのバグなのかということです。

4

0 に答える 0