3

下面的代码打印出 0 和 3。这是代码生成错误吗?我在 .NET 4.0 下使用 Visual Studio 2012 Update 3 RC 运行它

#include "stdafx.h"
using namespace System;
int main(array<System::String ^> ^args)
{
    unsigned long long d1 = 5, d2 = 3;
    auto arr = gcnew array<Object^, 2>(d1, d2);
    Console::WriteLine(arr->GetLength(0));
    Console::WriteLine(arr->GetLength(1));
    return 0;
}

更新:我已在https://connect.microsoft.com/VisualStudio/feedback/details/788830/c-cli-2-dimensional-array-allocation-with-unsigned-long-long-size-提交了连接错误报告参数生成无效代码

4

1 回答 1

3

是的,这绝对像虫子一样嘎嘎作响。unsigned long long编译器为此代码生成了错误的 IL,它似乎对必须将其转换为 int感到非常困惑。您可以通过运行 ildasm.exe 来查看错误的 IL,相关代码段为:

  IL_000a:  ldloc.3
  IL_000b:  conv.i4
  IL_000c:  ldloc.2
  IL_000d:  conv.i4
  IL_000e:  conv.i8             // <=== here!
  IL_000f:  newobj     instance void object[0...,0...]::.ctor(int32,
                                                              int32)

地址 IL_000e 处的指令是麻烦制造者,它将 IL_000d 生成的 int 转换回 8 位整数。然后,这会摸索传递给数组构造函数的参数。奇怪的是,IL 验证器也没有捕捉到它。

这不是更新 3 错误,这在 VS2008 中也以完全相同的方式失败,所以这肯定是一个老问题。它对于从 unsigned long long 到 System::Int32 的强制转换也非常具体,它不会在 long long 中出错。这可能是长期以来未被发现的原因。请注意,编译器会为此代码发出警告,抱怨它必须将 unsigned long long 截断为 int。因此,通过打开 /WX 进行编译来捕获此故障。

错误和警告的解决方法是自己显式转换变量:

auto arr = gcnew array<Object^, 2>((int)d1, (int)d2);

您可以在 connect.microsoft.com 提交此问题。如果您不想花时间这样做,请告诉我,我会处理的。

于 2013-05-28T11:01:23.423 回答