2

C 中程序的最大堆大小是固定的,还是如果我继续 malloc-ing 它会在某个时候开始溢出?

代码:

 while(connectionOK) //connectionOK is the connection with server which might be forever
 {
    if(userlookup_IDNotFound(userID))
     user_struct* newuser = malloc(getsize(user_struct));
     setupUserAccount(newuser);
 }

如果这很重要,我在 ubuntu/linux 中使用 gcc。我知道像 getrlimit 这样的东西,但不确定它是否给出堆大小。尽管它确实为输入参数中的选项之一提供了默认堆栈大小。此外,valgrind 可能是一个很好的工具,如这里建议的如何获取程序的堆大小,但如果存在堆溢出,我想动态打印错误消息。我的理解是操作系统在进程创建开始时分配的进程地址空间(如果它愿意,它实际上可以使用整个内存),但我不确定它是否会在请求时动态分配更多物理内存额外的内存。

4

3 回答 3

3

堆永远不会溢出它只是在某个点耗尽内存(通常是在malloc()返回时NULL)所以要检测内存不足只需检查调用的返回值malloc()

if (newuser == NULL)
{
    printf("OOM\n");
    exit(1); /* exit if you want or can't handle being OOM */
}

malloc()内部将从操作系统请求更多内存,因此它会动态扩展,因此它不是真正固定的大小,因为它会将不再需要的页面返还给操作系统,并在需要它们的任何给定时间请求更多。

于 2013-02-04T22:49:35.980 回答
2

从技术上讲,malloc在大多数系统上分配的不是内存,而是地址空间。在现代系统上,您可以轻松地使用 malloc 分配数 PB 的地址空间,而 malloc 可能总是返回一个非空指针。这背后的原因是,大多数操作系统实际上仅在主动修改一块地址空间时才执行内存分配。只要它原封不动地坐在那里,操作系统就会记录下进程地址空间的某个区域已被有效保留以供将来使用。

这种行为称为“内存过度使用”,在维护 Linux 系统时非常重要。如果可能发生,则分配的内存在一段时间内超过可用内存,然后某些程序实际上会写入一些过度使用的内存。然后发生的事情是,所谓的“Out Of Memory Killer”(OOM 杀手)将横冲直撞并杀死它认为最合适的那些进程;不幸的是,它通常是您在任何情况下都不想放松的那些过程。众所周知,数据库是 OOM 杀手的主要目标之一。

因此,强烈建议在高可用性 Linux 机器上切换内存过度使用。在禁用内存过量使用的情况下,每个地址空间请求都必须由内存支持。在这种情况下,如果请求无法完成,malloc 实际上会返回 0。

于 2013-02-04T23:11:10.480 回答
1

在某些时候,当系统内存不足时,malloc()将返回。NULL然后,当您尝试取消引用时,您的程序将中止执行。

malloc(SIZE_MAX)看看你做几次会发生什么:-)

于 2013-02-04T22:49:58.663 回答