C中的堆大小限制

3

关于C程序执行布局图中堆的问题,我有一个疑问。

我知道所有动态分配的内存都分配在堆中,而堆是动态增长的。但我想知道C程序的最大堆大小是多少?

这里我只是附上了一个简单的C程序...我试图为字符串分配1GB的内存并进行memset操作...

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

    int main(int argc, char *argv[])
    {
       char *temp;
       mybuffer=malloc(1024*1024*1024*1);

       temp = memset(mybuffer,0,(1024*1024*1024*1));

       if( (mybuffer == temp) && (mybuffer != NULL))
       printf("%x - %x\n", mybuffer, &mybuffer[((1024*1024*1024*1)-1)]]);
       else
       printf("Wrong\n");

       sleep(20);
       free(mybuffer);
       return 0;
    }

如果我同时在3个实例中运行上述程序,那么malloc应该至少在一个实例中失败[我这样认为]...但是仍然成功了。
如果它成功了,我能知道操作系统如何处理3GB的动态分配内存吗?
4个回答

8
你的机器很可能在RAM上过度提交,并且直到实际写入内存才开始使用它。尝试在分配每个块后写入该块,从而强制操作系统确保将真正的RAM映射到malloc()返回的地址。

+1 只需每页写入一个字节即可强制内存提交。 - Pascal Cuoq
我在分配的动态内存上尝试了memset...当我运行两个实例时,它似乎运行正常。 - codingfreak
1
写入不会改变任何东西,只会强制内核开始交换。当交换和 RAM 都满了时,Linux 内核开始杀死进程 (http://www.xenotime.net/linux/doc/swap-mini-howto.txt)。据我所知,由于系统缺少物理内存,您永远不会看到 malloc 返回 NULL。但是,由于您的进程使用了“太多”的虚拟地址空间,因此可能会返回 NULL。这在这里得到了很好的解释:http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory - nico

7
从Linux malloc页面来看,
BUGS
       By  default,  Linux  follows  an optimistic memory allocation strategy.
       This means that when malloc() returns non-NULL there  is  no  guarantee
       that  the  memory  really  is available.  This is a really bad bug.  In
       case it turns out that the system is out of memory, one  or  more  pro‐
       cesses  will  be  killed  by the infamous OOM killer.  In case Linux is
       employed under circumstances where it would be less desirable  to  sud‐
       denly lose some randomly picked processes, and moreover the kernel ver‐
       sion is sufficiently recent, one can  switch  off  this  overcommitting
       behavior using a command like:

           # echo 2 > /proc/sys/vm/overcommit_memory

       See  also  the  kernel  Documentation  directory,  files vm/overcommit-
       accounting and sysctl/vm.txt.

1

我知道虚拟内存的相关知识……我只是留下了有关我的内存详细信息的资料。 - codingfreak
你在问为什么在只有1GB内存的情况下分配3GB不会失败。假设你通过malloc使用了3GB内存,实际上你使用的是3GB虚拟页面。当系统内存不足时,它会将之前分配的页面存储到磁盘上的交换空间中,以便为新页面释放一些内存。请参考这个链接:http://apollo.lsc.vsc.edu/metadmin/references/sag/x1752.html - nico
但是我的交换分区利用率为0%,这是什么意思? - codingfreak
这意味着系统根本没有使用交换空间。但正如unwind所说,调用malloc并不实际分配内存。页面是惰性分配的,这意味着系统仅在您访问它(读取或写入)时才为您提供页面。 - nico
当我说完全不使用交换时,我的意思是尚未使用交换。 - nico

1

malloc函数会分配内存,但不会对其进行任何写入。因此,如果虚拟内存可用,则它将成功。只有当您向其中写入内容时,实际内存才需要分页到页面文件。

calloc函数会在返回之前将分配的内存中的每个字节写零,因此需要立即分配页面。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接