3

我正在开发一个程序,该程序在内存中存储大约 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 问题似乎是关于同样的问题;它的相似性甚至达到了分配较小内存量的程度(但 450 MB 没有)。那里的答案表明内存碎片很高,并且 new / malloc 无法分配连续的内存区域,但在我的情况下,即使在重新启动后,当 2 个物理 GB(和 4 个虚拟 GB)中只有 ~ 600 MB 时,问题仍然存在使用过,所以它在某种程度上被排除了(此外,就像我提到的,完全相同的代码行之前已经工作过)。

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

4

1 回答 1

2

内存分配失败是由于地址空间不足,而不是 RAM 不足。当程序被分页到磁盘时,缺少 RAM 会导致程序运行缓慢和大量磁盘抖动。

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

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

于 2013-08-12T08:30:24.417 回答