c++-cli - VS2015 C++/CLI Release Build 中的 NullReferenceException

标签 c++-cli visual-studio-2015 cil

我收到“System.NullReferenceException:未将对象引用设置为对象的实例”。在我的发布版本上。我创建了一个示例应用程序,它模仿了我的生产代码中的内容。

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.
    }
}

使用上面的代码,它报告的异常行是:at Abc.LogService.Log(String message) in logservice.cpp:line 19对应于 throw ex;代码中的声明。

此功能的发布版本中的 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

从 MSIL 代码中可以看出,在语句 IL_0028 处,它加载了一个空值并在后续语句中调用了 throw。
奇怪的是,只有当我有 try-finally 块时才会发生这种情况。
上述代码的调试版本工作正常。

这听起来像是 VS2015 v140 工具包中的错误吗?

最佳答案

是的,这是一个优化器错误。非常不寻常,我看到的第一个 C++/CLI 是一种应该由抖动来完成繁重工作的语言。它似乎通过声明 ex 被绊倒了。 try 块内的变量,让它在初始化保证上阻塞。看起来像一个流分析错误。

除了使用/Od 编译之外,一种解决方法是将变量移出 try 块

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

还产生了更好的 MSIL,完全消除了变量:
.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 上报告

关于c++-cli - VS2015 C++/CLI Release Build 中的 NullReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33515304/

相关文章:

mysql - VC++ 将数组<unsigned char>^存储在MySql数据库中

visual-studio-2015 - VS 2015 更新 3 远程调试器下载

c# - PowerShell 是否编译脚本?

c# - F# "unmanaged"类型约束的行为

c# - vs 2015 的代码合约现在稳定吗?

.net - 检测字符串

pointers - 如何在 VS 2008 C++ 中用消息框显示指针地址

c++-cli - HashSet <T>在VS2012中哪里去了?

c# - 使用.net套接字的文件,传输问题

nuget - 将符号包推送到符号服务器的问题