【问题标题】:Program heap size?程序堆大小?
【发布时间】:2013-01-19 18:26:15
【问题描述】:

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

代码:

 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 可能是这里建议的好工具how to get Heap size of a program,但如果存在堆溢出,我想动态打印错误消息。 我的理解是操作系统在进程创建开始时分配的进程地址空间(如果它愿意的话,它实际上可以使用整个内存),但我不确定它是否会在请求时动态分配更多物理内存增加内存。

【问题讨论】:

    标签: c unix memory-management


    【解决方案1】:

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

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

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

    【讨论】:

    • 唉,有些系统(比如 Linux)会过度使用,这意味着 malloc 可能在应该返回 NULL 时返回 NULL,而不是在您尝试使用过度使用时内存 OOM 杀手被调用。
    • @dmckee 旧的 Linux OOM 杀手,这是由于零页面和按需分配,第一次访问时页面会出错。我不确定是否有办法解决这个问题(也许MAP_POPULATE 标记为mmap?)
    • 您显然可以禁用过度使用。不知道那是在启动时,还是什么?谷歌搜索disable linux overcommit 会出现各种链接
    • @dmckee 我不建议这样做,除非您希望一半的程序停止运行。按需分配适用于基于 java 的进程,其中 java 决定一次分配大量内存并且从不使用它。从技术上讲,任何过度使用内存的东西都会停止运行(几乎所有东西)。
    【解决方案2】:

    在某些时候,malloc() 将返回NULL,此时系统将耗尽内存。那么当您尝试取消引用时,您的程序将中止执行。

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

    【讨论】:

    • SIZE_MAX 即使是第一次也几乎肯定会失败,因为这往往是该处理器(模式)中的整个可寻址范围,这意味着堆无法应对。跨度>
    【解决方案3】:

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

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

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

    【讨论】:

    • 问题是地址空间饥渴的应用程序(通常是基于 java 的应用程序)往往会占用系统上的大部分可用内存,而在某些情况下实际上并没有使用它。
    • @JesusRamos:原因是,表现出这种行为的程序将用一些值初始化分配的地址空间。操作系统将此视为内存修改,然后会为其分配实际内存。
    猜你喜欢
    • 1970-01-01
    • 2015-02-13
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 2016-04-05
    相关资源
    最近更新 更多