我有一个采访问题,当我们在无限循环中使用malloc()
分配大块内存并且不free()
时会发生什么。
我想用NULL
检查条件,当堆上没有足够的内存并且它应该打破循环时应该工作但是它没有发生,程序通过打印killed
异常终止。
为什么会发生这种情况以及为什么在没有内存要分配的情况下它不执行if
部分(我的意思是当malloc()失败时)?这是什么行为?
我的代码是:
#include<stdio.h>
#include<stdlib.h>
int main(void) {
int *px;
while(1)
{
px = malloc(sizeof(int)*1024*1024);
if (px == NULL)
{
printf("Heap Full .. Cannot allocate memory \n");
break;
}
else
printf("Allocated \t");
}
return 0;
}
编辑:gcc - 4.5.2(Linux- Ubuntu -11.04)
答案 0 :(得分:1)
如果你在linux上运行,请留意第一个终端。它将显示如下内容:
OOM error - killing proc 1100
OOM意味着内存不足。
我认为它在dmesg
和/或/var/log/messages
和/或/var/log/system
中也可见,具体取决于Linux发行版。你可以用:
grep -i oom /var/log/*
你可以让你的程序慢慢抓住记忆,并留意:
watch free -m
您会看到可用的交换进行下调和下调。当它几乎没有任何东西时,Linux会杀死你的程序,可用内存量会再次增加。
这是解释free -m
:http://www.linuxatemyram.com/
这种行为可能是我的init启动的应用程序或其他保护机制(如“上帝”)的问题,您可以进入一个循环,其中linux杀死应用程序和init或某些东西再次启动它。如果所需的内存量远大于可用的RAM,则通过将内存页交换到磁盘会导致速度变慢。
在某些情况下,linux不会杀死导致问题的程序,而是其他一些进程。例如,如果它杀死init,则机器将重新启动。
在最糟糕的情况下,一个程序或一组进程将请求大量内存(比Ram中可用的更多)并尝试重复访问它。 Linux无法快速放入内存,所以它必须将一些Ram页面交换到磁盘(交换分区)并加载从磁盘访问的页面,以便程序可以查看/编辑它。
每隔几毫秒就会一次又一次地发生这种情况。由于磁盘比RAM慢1000倍,因此这个问题可能会导致机器停止运行。
答案 1 :(得分:1)
行为取决于ulimits - 请参阅http://www.linuxhowtos.org/Tips%20and%20Tricks/ulimit.htm
如果您对内存使用有限制,您将看到预期的NULL返回行为,另一方面,如果您不受限制,您可能会看到您看到的OOM收割机等。
答案 2 :(得分:1)
但它没有发生,程序因打印被杀而异常终止。
请记住,你并不孤单。在这种情况下,你被Out Of Memory杀手杀死,它看到你的进程占用了系统的内存,并采取措施阻止它。
为什么会发生这种情况以及为什么在没有内存要分配的情况下它不执行if部分(我的意思是当malloc()失败时)?这是什么行为?
嗯,没有理由认为if
检查没有运行。查看malloc()
的{{3}}
默认情况下,Linux遵循乐观的内存分配策略。 这意味着当malloc()返回非NULL时,无法保证内存确实可用。如果事实证明系统内存不足,那么一个或多个进程将被OOM杀手杀死。
所以你认为你通过NULL
检查“保护”自己免受内存不足的影响;实际上它只意味着 如果 你回来了NULL
,你就不会对它有所尊重,这对于你是否真的得到你要求的内存没有任何意义