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

为什么这个C程序不会崩溃?,c,memory,malloc,C,Memory,Malloc,这是书中的: 如果内存被重新分配,然后丢失,则程序 可能在需要更多内存但malloc无法分配时终止 因为它的内存不足。在极端情况下,操作系统 可能会崩溃。以下简单示例对此进行了说明: 变量块是从内存分配的 堆。但是,在另一个内存块之前不会释放该内存 内存分配给它。最终,应用程序将耗尽所有资源 记忆和异常终止 因此,我的问题是: 我有以下示例代码: int main(int argc, char *argv[]){ char *chunk; while (1) {

这是书中的:

如果内存被重新分配,然后丢失,则程序 可能在需要更多内存但malloc无法分配时终止 因为它的内存不足。在极端情况下,操作系统 可能会崩溃。以下简单示例对此进行了说明:

变量块是从内存分配的 堆。但是,在另一个内存块之前不会释放该内存 内存分配给它。最终,应用程序将耗尽所有资源 记忆和异常终止

因此,我的问题是: 我有以下示例代码:

int main(int argc, char *argv[]){
    char *chunk; 
    while (1) {
        chunk = (char*) malloc(100000000);
        printf("Allocating\n"); 
    }
}
我希望我的系统内存耗尽,但程序一直在运行,我看到了文本

Allocating...
一直以来?

我想是在Linux上吧

仅仅因为你得到了一个指针并不意味着你实际上保留了那个内存。你必须亲自触摸页面,它才是你的

我想是在Linux上吧


仅仅因为你得到了一个指针并不意味着你实际上保留了那个内存。你必须亲自触摸页面,它才是你的

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

当内存不足时,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和unix通常会对系统上运行的进程施加一些限制。在linux中,所有这些限制在默认情况下都是不受限制的

当linux中的进程试图获得比系统更多的内存并分配剩余的虚拟内存时,内核会选择一个进程—最好的候选进程是尝试吃掉所有内存并杀死它以恢复一些内存。这也许就是为什么你读的文本说它异常终止的原因。您注意到这一点是因为系统在尝试交换您正在分配的所有内存时经过了一段时间,而交换程序需要所有的内核关注,所以您的系统似乎会挂起一段时间——它不会,只是等待

但是您可以进行这种测试:尝试使用ulimit命令限制分配给进程的虚拟内存,请参见bash1,这样系统就可以处理占用内存的程序。使用命令

$ ulimit -v 100000 # this allows for 100.000 kb of virtual memory
然后重新运行该程序,它将能够扩展到100Mb,不能再扩展了。你会发现它不会停止。它永远运行。一旦用尽所有内存,malloc3就会开始返回NULL,并且进程永远不会停止。您将通过ps1命令看到,程序已分配到您施加的限制,并且不再分配,并且它正在运行,消耗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);
}

你会看到这低于100Mb所以,瞧

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

Linux和unix通常会对系统上运行的进程施加一些限制。在linux中,所有这些限制在默认情况下都是不受限制的

当linux中的进程试图获得比系统更多的内存并分配剩余的虚拟内存时,内核会选择一个进程—最好的候选进程是尝试吃掉所有内存并杀死它以恢复一些内存。这也许就是为什么你读的文本说它异常终止的原因。您注意到这一点是因为系统在尝试交换您正在分配的所有内存时经过了一段时间,而交换程序需要所有的内核关注,所以您的系统似乎会挂起一段时间——它不会,只是等待

但是您可以进行这种测试:尝试使用ulimit命令限制分配给进程的虚拟内存,请参见bash1,这样系统就可以处理占用内存的程序。使用命令

$ ulimit -v 100000 # this allows for 100.000 kb of virtual memory
然后重新运行该程序,它将能够扩展到100Mb,不能再扩展了。你会发现它不会停止。它永远运行。一旦用尽所有内存,malloc3就会开始返回NULL,并且进程永远不会停止。您将通过ps1命令看到,程序已分配到您施加的限制,并且不再分配,并且它正在运行,消耗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);
}

你会看到这低于100Mb所以,瞧

而且,你不能用这些记忆做任何事情。那么它为什么要崩溃呢?即使它不能分配任何东西,malloc也会返回NULL,然后继续播放。malloc本身不应该崩溃。如果无法分配,它将返回NULLmemory@KorayTugay人们可能会投反对票,因为你没有解释为什么你认为它会崩溃。总是解释你的想法和原因。@KorayTugay,不,你不是

t不断分配新的100 Mbs。您不断尝试分配100 MB。这不是同一件事。malloc的手册,其中特别是返回值和错误(如果有的话)。此外,你不需要使用这个内存。那么它为什么要崩溃呢?即使它不能分配任何东西,malloc也会返回NULL,然后继续播放。malloc本身不应该崩溃。如果无法分配,它将返回NULLmemory@KorayTugay人们可能会投反对票,因为你没有解释为什么你认为它会崩溃。始终解释您认为正在发生的事情以及原因。@KorayTugay,不,您没有不断地分配新的100Mbs。您不断尝试分配100 MB。这不是同一回事。手册中有malloc,特别是返回值和错误(如果有)。你是说它会在第一次读/写时崩溃?不大可能发生的当然,如果不为null..我在循环中添加了这一行,仍然没有崩溃:*chunk='c';你只翻了一页。您需要按顺序触摸每个页面,然后等待它填满RAM和页面文件/交换@尤金,第一次读写的时候?不,我从来没有说过。@Blindy,那么你所说的触摸是什么意思?@nos不是vm.Overmit_memory=2吗?根据So,您是说它在第一次读/写时会崩溃?不大可能发生的当然,如果不为null..我在循环中添加了这一行,仍然没有崩溃:*chunk='c';你只翻了一页。您需要按顺序触摸每个页面,然后等待它填满RAM和页面文件/交换@尤金,第一次读写的时候?不,我从来没有说过。@Blindy,那么你所说的触摸是什么意思?@nos不是vm.Overmit_memory=2吗?根据这一点,如果您从未接触过Linux返回的页面,Linux将返回有效值。当访问不再适合虚拟内存的页面时,它会崩溃。我不知道为什么会有这样的结果,这不是Linux中的情况。我在cygwin上尝试了这段代码。过了一段时间,我收到了不成功的消息。@RSahu,再次阅读理解。Windows实际上在返回内存之前保留了内存。平心而论,OP没有提到他在哪个平台上运行。请不要在malloc的返回值中使用类型转换。没错,如果你从未接触过它返回的页面,Linux将返回有效值。当访问不再适合虚拟内存的页面时,它会崩溃。我不知道为什么会有这样的结果,这不是Linux中的情况。我在cygwin上尝试了这段代码。过了一段时间,我收到了不成功的消息。@RSahu,再次阅读理解。Windows实际上在返回之前保留了内存。公平地说,OP没有提到他运行的平台。请不要在malloc的返回值中使用类型转换。