【问题标题】:malloc() inside an infinte loopmalloc() 在无限循环中
【发布时间】:2012-12-17 19:45:20
【问题描述】:

我有一个面试问题,当我们在无限循环中使用malloc() 分配大块内存而不是free() 它时会发生什么。

我想用NULL检查条件应该在堆上没有足够的内存并且应该打破循环时工作,但是它没有发生并且程序通过打印killed异常终止。

为什么会发生这种情况以及为什么在没有内存要分配时(我的意思是 malloc() 失败时)不执行 if 部分?这是什么行为?

我的代码是:

#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)

【问题讨论】:

  • 我认为这是一种系统保护机制,当它需要内存时,它会杀死最消耗内存的进程
  • documentation for malloc 表示如果函数未能分配请求的内存,它将返回 null,但它没有说明可能发生这种情况的条件。
  • @koopajah : 感谢这个链接.. 我之前找不到那个
  • 通常程序被限制在整个系统崩溃之前吃掉内存,因为一个内存猪。

标签: c crash malloc free std


【解决方案1】:

如果您在 linux 上运行,请留意第一个终端。它将显示如下内容:

OOM error - killing proc 1100

OOM 表示内存不足。

我认为它在dmesg 和/或/var/log/messages 和/或/var/log/system 中也可见,具体取决于Linux 发行版。您可以使用 grep:

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 倍,因此这个问题可能会使机器陷入停顿。

【讨论】:

  • 感谢您提供详细信息..很有用
  • 还有一件事.. 这意味着在这种情况下 malloc 甚至不会失败一次.. 对吗?因为如果它会,那么它必须进入 if 情况,因为返回 NULL
  • 是的,linux malloc 默认情况下是惰性/乐观的 - 它实际上直到一段时间后才会保留内存。您可以使用以下命令将其关闭: echo 2 > /proc/sys/vm/overcommit_memory;请参阅此处的第 9.6 节:win.tue.nl/~aeb/linux/lk/lk-9.html - 还要小心该命令,我是在我的机器上完成的,它立即杀死了 chrome :)
【解决方案2】:

行为取决于 ulimit - 请参阅 http://www.linuxhowtos.org/Tips%20and%20Tricks/ulimit.htm

如果您对内存使用有限制,您会看到预期的 NULL 返回行为,另一方面,如果您没有限制,您可能会看到您看到的 OOM 收割机等。

【讨论】:

    【解决方案3】:

    但这并没有发生,程序通过打印killed异常终止。

    请记住,您并不孤单。在这种情况下,你被 Out Of Memory 杀手杀死了,它看到你的进程占用了系统的内存,并采取了措施来阻止它。

    为什么会发生这种情况以及为什么在没有内存要分配时(我的意思是当 malloc() 失败时)不执行 if 部分?这是什么行为?

    嗯,没有理由相信if 检查没有运行。查看man page 以获取malloc()

    默认情况下,Linux 遵循乐观的内存分配策略。 这意味着当 malloc() 返回非 NULL 时,不能保证内存确实可用。如果发现系统内存不足,OOM 杀手将杀死一个或多个进程。

    所以您认为您通过NULL 检查“保护”了自己免受内存不足的影响;实际上,这仅意味着如果你得到了NULL,你就不会尊重它,这对于你是否真的得到了你请求的内存没有任何意义。

    【讨论】:

    • 在澄清第一个问题时.. 这个 OOM 内存不足是否仅在 linux 或 Windows 或其他版本的操作系统中?其他的事情解释得很好..谢谢
    • @Omkant - OOM 是一个 Linux 工具,Windows 没有这样的保护,你可以很容易地杀死 Windows。
    • 哦,好吧,我会在 windows 上试试。还有一件事..这意味着 malloc 在这种情况下甚至不会失败一次..对吗?因为如果它会,那么它必须进入if案例,因为NULL的返回。
    • @Omkant - 这意味着malloc() 没有返回NULL,如果它返回NULL 那么是的,你的代码应该已经捕获了它。
    猜你喜欢
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2012-12-24
    • 2015-06-25
    • 1970-01-01
    相关资源
    最近更新 更多