2015-11-04 7 views
6

"System.NullReferenceException:オブジェクト参照がオブジェクトのインスタンスに設定されていません。"私のリリースビルドで。私は、プロダクションコードにあるものを模倣するサンプルアプリケーションを作成しました。上記のコードではVS2015のNullReferenceException C++/CLIリリースビルド

void Abc::LogService::Log(String^ message) 
{ 
    try 
    {  
     int ret = DoProcessing(message); 
     Exception^ ex; 
     if (ret == 0) 
     { 
      ex = gcnew ArgumentException("Processing done."); 
     } 
     else 
     { 
      ex = gcnew ArgumentNullException("message", "Null args"); 
     } 
     throw ex; 
    } 
    finally 
    { 
     //do someother thing. 
    } 
} 

、それがあることを例外ラインをレポート:コード内throw ex;ステートメントに対応 at Abc.LogService.Log(String message) in logservice.cpp:line 19。この機能のリリースビルドで

MSILのように見えます:MSILコードから

.method public hidebysig instance void Log(string message) cil managed 
{ 
    // Code size  46 (0x2e) 
    .maxstack 4 
    .locals ([0] class [mscorlib]System.Exception V_0, 
      [1] class [mscorlib]System.Exception ex) 
    .try 
    { 
    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: call  instance int32 Abc.LogService::DoProcessing(string) 
    IL_0007: ldnull 
    IL_0008: stloc.1 
    IL_0009: brtrue.s IL_0018 
    IL_000b: ldstr  "Processing done." 
    IL_0010: newobj  instance void [mscorlib]System.ArgumentException::.ctor(string) 
    IL_0015: stloc.0 
    IL_0016: br.s  IL_0028 
    IL_0018: ldstr  "message" 
    IL_001d: ldstr  "Null args" 
    IL_0022: newobj  instance void [mscorlib]System.ArgumentNullException::.ctor(string, 
                        string) 
    IL_0027: stloc.0 
    IL_0028: ldloc.1 
    IL_0029: throw 
    IL_002a: leave.s IL_002d 
    } // end .try 
    finally 
    { 
    IL_002c: endfinally 
    } // end handler 
    IL_002d: ret 
} // end of method LogService::Log 

、それはステートメントIL_0028で、それがNULL値をロードし、それに続く文でスローを呼び出すことを示しています。 これは、try-finallyブロックがある場合にのみ発生します。 上記のコードのデバッグビルドは正常に動作します。

これはVS2015 v140ツールキットのバグとして聞こえますか?

答えて

3

はい、これはオプティマイザのバグです。非常に珍しい、最初に私はC++/CLIのために見ました、ジッターが重い持ち上げをすることになっている言語。それはtryブロック内のex変数を宣言し、初期化の保証を犠牲にすることによってトリップされたように見えます。フロー解析のバグのように見えます。/ODでコンパイルからショート

は、1つの回避策は、tryブロックの外に変数を移動することです。また、完全に可変の排除、はるかに優れたMSILを生成

void Log(String^ message) { 
    Exception^ ex; 
    try { 
     // etc... 
} 

.method public hidebysig instance void Log(string message) cil managed 
{ 
    // Code size  41 (0x29) 
    .maxstack 4 
    .try 
    { 
    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: call  instance int32 Test::DoProcessing(string) 
    IL_0007: brtrue.s IL_0015 
    IL_0009: ldstr  "Processing done." 
    IL_000e: newobj  instance void [mscorlib]System.ArgumentException::.ctor(string) 
    IL_0013: br.s  IL_0024 
    IL_0015: ldstr  "message" 
    IL_001a: ldstr  "Null args" 
    IL_001f: newobj  instance void [mscorlib]System.ArgumentNullException::.ctor(string, 
                        string) 
    IL_0024: throw 
    IL_0025: leave.s IL_0028 
    } // end .try 
    finally 
    { 
    IL_0027: endfinally 
    } // end handler 
    IL_0028: ret 
} // end of method Test::Log 

オプティマイザのバグをあなたはconnect.microsoft.comで報告することができます