新操作符(以及malloc)无法分配~450MB的内存



我正在开发一个程序,该程序在内存中存储大约2.2亿个短值的数组。这个数据块是这样分配的:

short * arrayName = new short[SIZE_OF_ARRAY];

然后将文件的内容读取到内存中。在团队中的另一个人对程序的整体架构进行了大规模更新后,这条线开始使程序崩溃。信息是这样的:

Microsoft Visual C++ Runtime Library
Runtime Error!
abnormal program termination

它在调用内存分配时立即发生(不执行其他行,例如检查指针是否为NULL)。即使过了几天,我们也不清楚其他代码中的什么变化到底导致了这一行开始以这种方式运行(实际上,甚至与该数组远程链接的代码都没有变化)。

在Linux(确切地说是Ubuntu)上,一切都很正常;此问题仅存在于Windows计算机上。在64位Windows操作系统上,此解决方法有助于(在.pro文件中):

QMAKE_LFLAGS_WINDOWS += /LARGEADDRESSAWARE

在32位上,它没有帮助。

用malloc替换这一行可以让我检查指针后面是否为NULL(事实上),并从errno中获得错误代码,即12(ENOMEM)="内存不足"。

short * arrayName = (short *)malloc(SIZE_OF_ARRAY * sizeof(short));

这个StackOverflow问题似乎是关于同样的问题;它的相似性甚至达到了分配少量内存有效(但450MB不行)的程度。那里的答案表明内存碎片很高,新的/malloc无法分配连续的内存区域,但在我的情况下,即使在重新启动后,当2个物理GB(和4个虚拟GB)中只有约600 MB被使用时,问题仍然存在,因此在一定程度上排除了这种可能性(此外,正如我提到的,完全相同的代码行以前也工作过)。

我的主要怀疑是它与堆大小有关(尽管我不确定new和malloc是否都为堆分配内存;而且我还没有找到在Qt中更改堆大小的方法)。我是不是遗漏了什么?

内存分配失败的原因是缺少地址空间,而不是RAM。缺少RAM会导致程序运行缓慢,并且在程序被分页到磁盘时会导致大量磁盘抖动。

/LARGEADDRESSAWARE告诉操作系统,您的应用程序可以接受更大的地址空间。Win64将为Win32应用程序提供3GB的地址空间,在Win32上这不是标准的。

关闭ASLR会有所帮助,因为它将以线性方式加载DLL(因此以可预测的偏移量加载,这是一个安全风险)。使用ASLR,DLL分散在内存中。由于只有10个DLL分散在2GB的地址空间中(这是不切实际的低),它们之间的平均空间约为200MB。

相关内容

  • 没有找到相关文章

最新更新