我正在开发一个程序,它在内存中存储大约220万个短值的数组。这个数据块的分配如下:
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));
This StackOverflow question似乎是同一个问题;它的相似性甚至达到了分配较少量内存的作用(但450 MB不能)。那里的答案表明存在高内存碎片,并且new / malloc无法分配连续的内存区域,但在我的情况下,重启后问题仍然存在,当时2个物理GB(和4个虚拟GB)中只有~600 MB使用,所以它有点排除(另外,就像我提到的,完全相同的代码行之前已经工作过。)
我主要怀疑它与堆大小有关(虽然我不确定new和malloc是否都将内存分配给堆;而且我还没有找到一种方法来改变Qt中的堆大小) 。我在这里错过了什么吗?
答案 0 :(得分:2)
内存分配由于缺少地址空间而失败,而不是缺少RAM。由于程序被分页到磁盘,因此缺少RAM会导致程序运行缓慢,并导致大量磁盘抖动。
/LARGEADDRESSAWARE
告诉操作系统您的应用可以接受更大的地址空间。 Win64将为Win32应用提供3GB的地址空间,在Win32上这不是标准的。
关闭ASLR可以提供帮助,因为它将以线性方式加载DLL(因此可预测的偏移量,这是一种安全风险)。使用ASLR,DLL分散在内存中。由于只有10个DLL分散在2 GB的地址空间中(这是不切实际的低),它们之间的平均空间大约为200 MB。