我在负载测试期间检测到程序中的错误并进行了调查。乍一看,我认为我的代码中有错误。但是,它适用于较少量的数据,并按预期的步骤逐步执行。所以我将代码缩减为以下示例。没有处理,只有分配:
void main(void) {
const signed int n = 100000000; /* high on purpose */
signed int k;
char **Buffer = NULL;
Buffer = (char**) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, n * sizeof(char*));
if (!Buffer) {
printf("Fail to allocate the big buffer\n");
return;
}
for (k = 0; k < n; ++k) {
Buffer[k] = (char*) HeapAlloc(GetProcessHeap(), 0, 3 * sizeof(char)); /* using malloc also causes failure */
if (Buffer[k] == NULL) {
printf("Out of memory on buffer no. %d\n", k);
/* break; */
}
}
/* break point here */
for (--k; k >= 0; --k)
if (Buffer[k])
HeapFree(GetProcessHeap(), 0, Buffer[k]);
HeapFree(GetProcessHeap(), 0, Buffer);
}
计算机有12Go的RAM,没有页面文件(交换)。当我运行此代码时,内存消耗会按预期增加到我没有更多可用内存的程度。分配往往在结束时较慢,然后开始失败。之后,我的程序和其他应用程序崩溃,包括Windows(7 SP1 64位)和我的调试器(Visual Studio 2013)。 我不能使用break语句,因为代码将被放在 OpenMP 块中(我将使用标志)。不过,我测试了它并没有改变任何东西。
为什么它会让一切都崩溃?
这是我的猜测。当我分配大量少量内存的实例时,我可能会遇到剩余零页面(非常接近)的情况。所以其他应用程序既不能分配内存,也不能分配少量内存。他们可能要么不能很好地处理缺乏内存,要么绝对需要它并且崩溃。 Visual Studio或Windows可能会在崩溃时关注并崩溃我的应用程序。一旦我收到了带有 PAGE_FAULT_IN_NONPAGED_AREA 错误的BSD。
我的猜测是否正确导致事故或我错过了什么?我的代码是错误的还是有一个我不知道的已知错误?
我的真实代码接收一个输入,处理并存储它。是循环输入的用户。这个示例告诉我,检测分配失败不是正确的方法,因为它已经太晚了。还有关于如何防止这种情况的任何想法?在每次分配之前检查可用内存量肯定会导致性能下降。
此外,操作系统是否应该保留可用内存以防止单个程序全部使用?
这看起来像是一本教科书案例。但是我无法找到导致该错误的任何类似代码。
答案 0 :(得分:1)
内存管理行为因每个操作系统而异。我不熟悉Windows 7操作系统中实现的内存管理单元,但是当资源不足时,你可以做很少的事情(从内核的角度来看)。通常,操作系统更愿意终止请求大量资源的进程,这可能就是您的情况。
你已经指出了一个&#34;保留区域&#34;行为,但这不会解决问题,即使它已实现,因为如果区域被保留,您仍然需要决定哪些进程将使用它,哪些进程不会,导致不允许使用的进程它饿死(并停止)。当然,内核应该足够切碎,以便为自己的例程保留内存,以防止自身崩溃(所以我不知道为什么Windows内核会崩溃,但正如我所指出的,我不是熟悉其实施情况。)
我建议您从操作系统的角度阅读一些有关内存管理的文章或书籍(特别是关于Windows内存管理)。这将为您提供进一步研究的一些线索。
希望这有帮助。