【问题标题】:Growing memory during assignment of large array在分配大数组期间增加内存
【发布时间】:2014-03-12 23:25:54
【问题描述】:

将值分配给大型数组时,即使没有分配新内存,使用的内存也会不断增加。我只是通过任务管理器(windows)或系统监视器(Ubuntu)来检查使用的内存。

两个操作系统上的问题都是一样的。我分别使用 gcc 4.7 或 4.6。

这是我的代码:

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

int main(int argc, char *argv[]) {
    int i,j;
    int n=40000000;   //array size
    int s=100;
    double *array;

    array=malloc(n*sizeof(double));     //allocate array
    if(array==NULL){
        return -1;
    }

    for(i=0;i<n;i++){   //loop for array, memory increases during this loop
        for(j=0;j<s;j++){   //loop to slow down the program
            array[i] = 3.0;
        }
    }
    return 0;
}

我没有看到任何逻辑问题,但据我所知,我也没有超出任何系统限制。所以我的问题是:

  • 问题可以被其他人重现吗?

  • 内存增长的原因是什么?

  • 我该如何解决这个问题?

【问题讨论】:

标签: c++ c


【解决方案1】:

当现代系统“分配”内存时,页面实际上并未分配到物理 RAM 中。您将获得虚拟内存分配。当您写入这些页面时,将获取一个物理页面。因此,当您执行malloc() 时,占用的虚拟 RAM 会增加,但只有在您写入值时才会占用物理 RAM(逐页)。

【讨论】:

    【解决方案2】:

    您应该会看到使用的虚拟内存立即增加。之后,RSS 或使用的实际内存将随着您写入新分配的内存而增加。更多信息How to measure actual memory usage of an application or process?

    这是因为在 Linux 和许多其他操作系统上分配的内存在您使用它之前实际上并没有分配给您的程序。

    因此,您可以在 256 MB 的机器上 malloc 1 GB,并且在您真正尝试使用所有 1 GB 之前不会耗尽内存。

    在 Linux 中有一组过度使用设置可以改变这种行为。见Cent OS: How do I turn off or reduce memory overcommitment, and is it safe to do it?

    【讨论】:

    • 操作系统绝对允许您分配比物理可用内存更多的虚拟内存?
    • @OllieFord:默认情况下是的。然后,当程序使用所有可用的物理和交换内存时,它将被 OOM 杀死。记不清。但是 Linux 允许您根据需要将其更改为严格模式。
    • @ZanLynx 是正确的,除了即使您禁用过度使用,驻留大小也不等于首次分配时的虚拟大小。它只是防止分配的虚拟大小的总和超过物理内存。所以技术上它不会改变行为(分配中的虚拟/物理差异)。
    • @ZanLynx 有趣 - 谢谢。你知道为什么它是这样配置的吗?似乎是多余的。我可以理解其他程序当前是否正在使用此内存 - 但如果它比实际存在的更多,那么允许它似乎毫无价值?
    • @OllieFord:我知道的最大原因是实现fork()。成功分叉后,现在有两个进程。如果没有过度使用,每个人现在都需要完全提交其所有内存。如果它是一个在 4 GB 机器上使用 2 GB 的大型 Java 服务器进程并且它想要 fork/exec ls,这将失败而不会过度提交。
    猜你喜欢
    • 2012-01-24
    • 2014-11-13
    • 2014-01-10
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    相关资源
    最近更新 更多