繁体   English   中英

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

[英]How come this C program does not crash?

摘自本书: 理解和使用C指针

如果重复分配了内存然后又丢失了内存,则该程序可能在需要更多内存时终止,但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...

每时每刻?

当内存不足时, 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");
    }
}

我假设在Linux上?

仅仅因为返回指针并不意味着您实际上已经保留了该内存。 您必须亲自触摸页面才能使其成为您的页面。

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

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)所以,瞧!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM