c - 分配所有内存使我的系统崩溃

标签 c winapi memory-management heap-memory

我在负载测试期间检测到我的程序中存在错误并进行了调查。乍一看,我以为我的代码有错误。但是,它使用的数据量较小,并且按预期调试逐步执行。所以我将我的代码缩减为以下示例。没有处理,只有分配:

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 block 中(我将使用标志)。不过,我进行了测试,它并没有改变任何东西。

知道为什么它会导致一切崩溃吗?

这是我的猜测。当我分配少量内存的大量实例时,我可能会遇到剩余可用页面为零(或非常接近)的情况。所以其他应用程序也不能分配内存,即使是少量的。他们可能要么不能很好地处理内存不足,要么绝对需要它并崩溃。 Visual Studio 或 Windows 可能会担心并在崩溃时崩溃我的应用程序。一旦我得到一个带有 PAGE_FAULT_IN_NONPAGED_AREA 错误的 BSD。

我对导致崩溃的原因的猜测是正确的还是我遗漏了什么?是我的代码有误还是存在我不知道的已知错误?

我的真实代码接收一个输入、处理它并存储它。循环输入的是用户。这个示例告诉我,检测分配失败不是正确的方法,因为已经太晚了。你对如何防止这种情况有什么想法吗?在每次分配之前检查可用内存量肯定会破坏性能。

此外,操作系统不应该保留空闲内存以防止单个程序消耗所有内存吗?

这似乎是教科书般的案例。但是,我找不到导致该错误的任何类似代码。

最佳答案

内存管理行为因操作系统而异。我不熟悉 Windows 7 操作系统中实现的内存管理单元,但是当资源匮乏时,您几乎无能为力(从内核的角度来看)。通常,操作系统更愿意终止请求大量资源的进程,这可能就是您的情况。

你已经指出了一个“保留区域”的行为,但这不会解决问题,即使它被实现了,因为如果区域被保留,你仍然需要决定哪些进程将使用它,以及哪些进程不会,导致不允许使用它的进程饿死(并停止)。当然,内核应该足够清晰,为自己的例程保留内存,以防止自身崩溃(所以我不知道为什么 Windows 内核会崩溃,但正如我所指出的,我不熟悉它的实现).

我建议你从操作系统的角度阅读一些关于内存管理(特别是关于windows内存管理)的论文或书籍。这将为您提供一些进一步研究的线索。

希望这对您有所帮助。

关于c - 分配所有内存使我的系统崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23460214/

相关文章:

c - 如何以快速安全的方式将十六进制字符串转换为无符号 64 位 (uint64_t) 整数?

c - posix fork() & win32 CreateProcess() 之后的子进程名称是什么?

algorithm - "2D memory management"的高效算法

c++ - 有没有办法让缓冲函数不浪费那么多内存?

c - 了解 printf 吗?

c - 带有 NULL 超时的 select() 是否比带有超时的 select() 更轻?

c - isdigit() 有效电话号码的输入测试

c - 如何以编程方式确定 Windows 是否正在关闭?

delphi - 如何处理WM_ERASEBKGND以避免闪烁?

C++ 内存管理 : creating a new array from vectors in a function