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

C 动态内存分配。我错过了什么?,c,memory,operating-system,malloc,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 /

请查看此代码:

#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;
}
#包括
#包括
int main()
{
char*foo=(char*)malloc(500000000);
//当我取消注释下面的内容时,操作系统
//承认这个程序使用了500MB的内存
//这句话的意思是,它声称该程序几乎没有使用任何
//完全没有记忆,为什么会这样?
/*

对于(inti=0;i,在您使用之前,您的操作系统可能不会分配(或显示它已分配)内存


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

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

我遗漏了什么?操作系统使用了什么技巧,我应该读些什么

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

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

这是每页都会发生的。因此,如果在
for
中按系统上的页面大小增加
i
(可能是4096或类似的大小),您将获得相同的用法。作为一个简单的技巧,尝试使用
触摸的元素数。作为奖励,尝试通过将大小除以页面大小来预测内存使用量操作系统内存页面仅在您访问它们时才真正分配给您的进程(在您的情况下,通过写入)。具体行为取决于您的编译器和操作系统-在不同的系统上,您可能会发现内存会立即用完。

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

BTW,这是C而不是C++。注意,当你说“OS说进程使用N字节的内存”时,1Mb==1024kb= 108566B,500万字节是47。你说的是什么指标?人们用“内存”来表示(1)虚拟地址空间(2)特定进程专用的虚拟字节(3)物理内存(4)页面文件保留空间,(5)页面文件提交的空间和半打其他东西。完全有可能你一开始就看错了指标。请停止它@Davehiller!1MB==1000KB==1000000B!天哪,这是极少数让我如此恼火的事情之一。请尽快阅读以下内容:@gustafr什么更重要?要学究般地正确或者以其他人理解你的方式说话?国际单位制只是一种惯例,以确保人们相互理解。字节(不幸的是)使用不同的惯例。我知道malloc可能会失败。但情况似乎并非如此,因为我也尝试过:foo[0]=0;foo[4999…9]=0;它还声称进程使用的内存非常少。@chomzee不相信我的话。试试看事情是否真的是这样发生的。有一件事让我感到奇怪。如果当我“触摸”某个虚拟内存片段时,操作系统没有这样的惰性分配空间,会怎么样?
malloc
已经成功并返回了值。程序会不会鲁莽?@chomzee我认为操作系统一开始不会给你。无论如何,如果可能的话,它会尝试交换一些东西来腾出空间。但是,我也不认为它会超额订阅。大多数操作系统都会超额订阅。(如微软WIndows、Linux和达尔文)这也是malloc在64位机器上几乎从不失败的原因。@cnicutar显然,您可以在linux下控制过度承诺行为。请参阅链接。