我在工作中分析了一个c++/CLI项目,它有一个奇怪的内存签名:它有大量的已提交字节(7GB),但它在工作集中只有大约30MB。我发现问题出在下面这段代码中:
ref class c1
{
public:
int x;
static void createArray()
{
auto val = gcnew c1;
auto arr = gcnew array<c1^>(1) { val };
auto jagged= gcnew array<array<c1^>^>{ arr };
//Make sure the array doesn't get optimized away
Console::WriteLine(jagged[0][0]->x);
}
};
我期望jaged的初始化在c#中转换成这样的东西:
var jagged = new c1[][] { arr };
相反,使用ILSpy,我发现它实际上翻译成这样的东西(反编译优化的二进制文件:
public static void createArray()
{
c1 val = new c1();
c1[] array = new c1[]
{
val
};
c1[][] array2 = new c1[][]
{
new c1[12648430] //the constant is equal to 0xC0FFEE
};
array2[0] = array;
Console.WriteLine(array2[0][0].x);
}
我发现很难理解为什么它会分配一个12648430元素的临时数组。然而,我也很难想象这样的错误实际上是在Visual Studio 2013专业版MSVC编译器中发布的,但我想不出任何其他解释。
我错过了什么吗?
这实际上是c++/CLI编译器实现中的一个bug。微软已经意识到这个问题,但他们暂时不会修复它。
更多细节可以在这里的bug报告中找到。
报告还提出了两个简单的解决方法:
-
手动初始化数组,而不是使用初始化列表
-
使用二维数组代替锯齿数组