2

请看一下这段代码:

#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 时,操作系统应该说该进程正在使用超过 500MB 的内存。但显然,它不是那样工作的。我错过了什么?操作系统使用什么技巧,我应该阅读什么?

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

4

5 回答 5

7

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

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

  • malloc要求操作系统提供大量内存,操作系统会说:“当然,给你”并且(几乎)什么都不做
  • 操作系统暗地里希望你永远不要碰“分配”的页面
  • 当您触摸分配的页面时,操作系统会捕捉到不可避免的页面错误,叹息并分配页面

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

于 2013-01-06T21:06:30.970 回答
2

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

于 2013-01-06T21:05:56.687 回答
1

在您使用它之前,您的操作系统可能不会分配(或显示它已分配)内存。

无论如何,malloc()如果要分配如此大的块,检查的返回值是一个非常好的主意。malloc() 可能会失败,你知道的。

于 2013-01-06T21:05:32.797 回答
1

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

于 2013-01-06T21:07:15.063 回答
-1

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

于 2013-01-06T23:42:20.087 回答