c++ /CLI二维数组分配失败



下面的代码打印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-argument-generates-invalid-code上提交了一个连接错误报告

是的,这绝对像个虫子。编译器为这段代码生成了错误的IL,它似乎对必须将unsigned long long转换为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产生的整型转换回8位整数。然后,这会对传递给数组构造函数的参数进行处理。奇怪的是,IL验证器也没有捕捉到它。

这不是更新3的错误,这在VS2008中也以完全相同的方式失败,所以这肯定是一个老问题。它也高度特定于从unsigned long long到System::Int32的强制转换,它不会在long long中出错。可能的原因是这么长时间没有被发现。请注意,编译器会对这段代码发出警告,抱怨它必须将unsigned long截断为int型。因此,在/WX打开的情况下编译,可以捕获这个错误。

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

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

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

最新更新