为什么这个C程序不会崩溃?

时间:2015-04-13 16:32:16

标签: c memory malloc

这来自本书:Understanding and Using C Pointers

  

如果重复分配然后丢失内存,则程序   当需要更多内存但malloc无法分配时可能会终止   因为它耗尽内存。在极端情况下,操作系统   可能会崩溃。这在以下简单示例中说明:

char *chunk; 
while (1) { 
    chunk = (char*) malloc(1000000); 
    printf("Allocating\n"); 
} 
  

变量块从中分配内存   堆。但是,此内存不会在另一个块之前释放   内存被分配给它。最终,应用程序将耗尽   记忆并异常终止。

所以我的问题: 我有这个示例代码:

int main(int argc, char *argv[]){
    char *chunk; 
    while (1) {
        chunk = (char*) malloc(100000000);
        printf("Allocating\n"); 
    }
}

好吧我期待我的系统内存耗尽,但程序一直在运行,我看到了文本

Allocating...

一直在吗?

3 个答案:

答案 0 :(得分:6)

如果没有足够的内存malloc可能会返回NULL。添加一张支票。

while (1) {
    printf("Allocating\n"); 
    chunk = malloc(100000000);
    if ( chunk == NULL )
    {
       printf("Memory allocation not successful.\n");
    }
    else
    {
       printf("Memory allocation successful.\n");
    }
}

答案 1 :(得分:2)

在Linux上我假设?

仅仅因为你找回指针并不意味着你实际上保留了那个记忆。您必须亲自触摸该页面才能成为您的页面。

答案 2 :(得分:1)

您运行的程序不正确。它不必异常终止。提前终止的原因是它消耗了计算机中的所有内存,所以如果你没有采取正确的措施,它就会死掉。

Linux(以及一般的unix)对系统上运行的进程施加了一些限制。在linux中,默认情况下,所有这些限制(请参阅 ulimit(2)系统调用)都固定为unlimited

当linux中的进程尝试获得比系统更多的内存并分配剩余的虚拟内存时,内核会选择一个进程(最好的候选者是尝试占用所有内存的进程)并杀死它以恢复一些内存。这也许就是为什么你读到的文字说它会异常终止。你注意到这一点,因为系统通过一段时间尝试交换你正在分配的所有内存,并且交换器需要所有内核注意(所以你的系统似乎挂了一段时间---它没有,只是等待)

但是你可以做这种测试:尝试限制分配给进程的虚拟内存(使用ulimit命令,参见 bash(1)),这样系统就可以应对内存耗尽程序。使用命令

$ ulimit -v 100000 # this allows for 100.000 kb of virtual memory

并重新运行程序(它将能够扩展到100Mb而不会更多)。你会发现它并没有停止。它永远运行。一旦耗尽了所有内存, malloc(3)就会开始返回NULL并且进程永不停止。您将看到(通过 ps(1)命令)程序已分配到您施加的限制,并且不再运行,并且正在运行,占用了100%的CPU时间。一切都在掌控之中。我尝试了以下程序变体:

#include <stdlib.h>
#include <stdio.h>
char *chunk;
main()
{
    int i = 0;
    while (malloc(1000000)) i++; 
    printf("run for %i times.\n", i);
}

计算内存耗尽前的成功分配数,并在stdout上打印该数字。将ulimit修复为100Mb(ulimit -v 1000000)后,该程序输出:

$ pru
run for 97 times.

(你会看到它低于100Mb)所以,瞧!