为什么malloc()或new永远不会返回NULL?

rra*_*alf 17 c c++ memory-management

我正在编写一个应用程序,需要大量内存用于缓存目的,正如我在此描述的那样.现在我正在玩一些malloc/new结构来弄清楚我是如何实现它的.我做了一个奇怪的观察:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  while(1) {
    char *foo = (char*)malloc(1024);// new char[1024];
    if(foo == NULL) { 
      printf("Couldn't alloc\n");
      fflush(stdout);
      return 0;
    }
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么永远不会达到printf?如果我的系统运行的内存,malloc的据说返回NULL,因为它是解释在这里.但我总是收到SIGKILL(我正在使用linux ......).

Ant*_*ony 24

默认情况下,Linux通常使用机会内存分配方案,这意味着内核将为您提供一个在首次使用之前不会分配的有效地址.

看到:

根据这些回复,您可以关闭此功能echo 2 > /proc/sys/vm/overcommit_memory.

据我所知,这是在你不必使用你分配的所有内存的假设下完成的.我不能说我个人曾经分配过至少一次我没有碰过的空间,所以我很想知道这会影响现实生活中的表现......

关于SIGKILL失败,您调用的每个malloc仍然为每个调用分配一些内存.最终你可能会用malloc开销填满你的记忆,从而唤起内存终止杀戮功能的愤怒.这是否是问题,或者过度使用政策是否仍然分配了一小部分所需空间是一个很好的问题.

  • @rralf:因为并非每个系统都是Linux,并非每个Linux系统都使用默认设置,并且无法保证在默认设置下它不会返回NULL. (5认同)
  • @Anthony:一个例子是分配一个巨大的1GB临时工作区域,就像一些虚拟机和服务器进程那样.你绝对不会一次性使用它.您可能只需要几百MB的物理支持内存,其余的未使用或能够有效地移动到交换.请注意,Linux无法保证_never_返回NULL; 地址空间有一个上限,如果你耗尽所有这些,就不能"伪造"任何东西. (3认同)
  • @rralf因为也许明天Linux会被修改并删除这个"功能"?因为你的程序可能会在`overcommit_memory`设置为`2`的系统上运行?等等.TL; DR:因为这是**正确的事情. (2认同)

Mik*_*our 6

通常,Linux会根据您的请求分配尽可能多的(虚拟)内存,并且只在需要时为其分配物理内存.如果系统耗尽了物理内存,那么它会开始终止进程​​以释放一些内存.

这意味着malloc除非请求是荒谬的,否则将成功,但是您的进程(或其他一些)可能会因使用内存而被杀死.

有关更多详细信息,请参阅联机帮助页malloc及其参考:

默认情况下,Linux遵循乐观的内存分配策略.这意味着当malloc()返回非时NULL,不能保证内存确实可用.如果事实证明系统内存不足,那么一个或多个进程将被OOM杀手杀死.有关更多信息,请参阅/ proc/sys/vm/overcommit_memory和/ proc/sys/vm/oom_adj中的说明proc(5)以及内核源文件Documentation/vm/overcommit-accounting.

(当然new,除非你使用无投掷版本,否则不会返回null).