动态内存分配。我错过了什么?

时间:2013-01-06 21:02:26

标签: c memory operating-system malloc

请看一下这段代码:

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

int main()
{
    char* foo = (char*)malloc(500000000);

    // when I uncomment stuff that's below then operating system
    // admits that this program uses 500MB of memory. If I keep
    // this commented, it claims that the program uses almost no
    // memory at all. Why is it so?

    /*
    for (int i=0; i<500000000; i++)
    {
        foo[i] = (char)i;
    }
    */

    int bar; scanf("%d", &bar); // wait so I can see what's goin on

    free(foo);

    return 0;
}

我的直觉很简单。当我使用malloc调用分配500MB时,OS应该说该进程正在使用超过500MB的内存。但显然,它不会那样工作。我错过了什么?操作系统使用的技巧是什么,我应该阅读什么?

提前感谢您提供任何线索。

5 个答案:

答案 0 :(得分:6)

  

我错过了什么?操作系统使用的技巧是什么,我应该阅读什么

这是一种懒惰分配形式。简而言之:

  • malloc要求操作系统提供大量内存,操作系统会:“确定,在这里你去”而且几乎没有任何内容
  • 秘密操作系统希望你永远不会触及“已分配”页面
  • 当您执行触摸已分配的页面时,操作系统会捕获不可避免的页面错误,叹息并分配页面

每页都会发生这种情况。因此,如果在您的for中增加i系统中的页面大小(可能是4096或类似内容),您将获得相同的用法。作为一个简单的技巧,尝试使用for触及的元素数量。作为奖励,尝试通过将大小除以页面大小来预测内存使用情况

答案 1 :(得分:1)

您的操作系统可能无法分配(或显示已分配)内存,直到您使用它为止。

在任何情况下,检查malloc()的返回值是一个非常好的主意,如果你要分配这么大的块。你知道,malloc() 可以失败。

答案 2 :(得分:1)

进程中的所有内存使用都由操作系统虚拟化。您可能在代码中“分配”了一个内存块,但在代码实际使用之前,操作系统可能实际上并未将其提交给物理内存。

答案 3 :(得分:1)

操作系统内存页面只有在您访问它们时才真正分配给您的进程(在您的情况下通过写入)。确切的行为取决于您的编译器和操作系统 - 在不同的系统上,您可能会发现内存已立即用完。

答案 4 :(得分:0)

它与操作系统无关。编译器优化生成的代码,这样如果未使用分配的内存,则会删除在结果二进制文件中分配内存的语句。您可以通过将编译器优化级别设置为零来检查此问题。然后你将获得500MB的任何一种情况,因为每次都会分配内存。