在问之前,我先做一个小小的免责声明:是的,我知道虚拟内存、物理内存和工作集之间的区别。以下所有数字均指虚拟内存。
情况如下:我们有一个 32 位 C# 应用程序,它导入 x86 C++ 库(具有大量本机依赖项,因此目前无法迁移到 x64)。应用程序通过非托管组件加载一个大型数据集,然后尝试显示它(报告)。
但是,当数据集特别大时,将项目添加到列表时会引发 OutOfMemory 异常,如下面的代码所示:
这里没有惊喜。然而,令人惊讶的是,该应用程序仍有大约 280MB 的空闲 VM。
在调试纯非托管应用程序 (C++) 时,情况并非如此——只有在没有空闲 VM 或没有足够大小的空闲地址空间块时才能实现 bad_alloc。
因此,问题 - 这可能是什么原因?我了解如何解决这个问题 - 非托管组件确实会占用大量内存,并且会产生大量碎片 - 但是 OutOfMemoryException 这么早出现的原因是什么?
有问题的代码如下所示:
List<Cell> r = new List<Cell>(cols);
for (int j = 0; j < cols; j++)
{
r.Add(new CustomCell()); // The exception is thrown on this line
}
在异常的那一刻,列表(一次出现)有 85 个项目,它的容量是 200 左右(列数,如构造函数中所示)。因此,异常很可能发生在 CustomCell 分配中。CustomCell 对象有很多字段,但总和肯定小于 1KB。280MB 的空闲内存位于 64KB 到 14MB 的块中——所以应该有足够的空间来分配它。