在循环中使用 malloc 如何进行内存分配 >

How does memory allocation take place on using malloc in a loop >

在这种情况下,内存分配是如何进行的? 我观察到这与直接在 1000000*10000 上使用 malloc 不同,后者应该导致分配 4*10GB(每个 int 4 个字节)。然而,这段代码在执行时只使用了 200MB。

for(int i=0;i<1000000;i++)
{
    int *A = (int*)malloc(sizeof(int)*10000);
}

区别在于内存的分配方式。

当你调用10K次malloc分配10k内存时,10G的虚拟内存被分配给你的进程。由此产生的10G内存并不连续。也就是说,你得到了 10k 个大小为 10K 的分散内存块。然而,当您调用 malloc 请求 10G 时,malloc 将尝试分配大小为 10G 的连续内存块。

根据 malloc 手册页,malloc 在无法分配请求的内存时失败。您应该检查 malloc 在您的应用程序中是否成功,以了解内存是否已正确分配。

for(int i=0;i<1000000;i++)
{
    int *A = (int*)malloc(sizeof(int)*10000);
}

这是一个完美的内存泄漏方式。您正在分配 1000000 次,每次分配 sizeof(int)*10000 字节。您肯定会泄漏这些已分配内存的 all。当您在循环中声明 A 时,因此在循环之后您不再拥有该变量的句柄,并且甚至无法释放您分配的最后一块内存。

当然这与一次性分配 1000000*10000*sizeof(int) 不同。前者分配 1000000 个较小的块,这些块主要分散在许多内存位置。后者试图分配一个巨大的块,这很可能会失败。

如前所述,内存是按块分配还是单独分配是有区别的。您看不到正在分配的内存的主要原因是操作系统在内存方面存在问题。

如果分配一块内存,则分配是虚拟。由于所有进程都有大量可用的虚拟内存,它通常会成功(除非您要求疯狂的内存量,或者 OS 否则确定它不会工作)。物理内存的实际保留可能发生在您实际使用内存之后。

所以当您查看内存使用情况时,不仅有一个数字,还有多个。有共享内存,有不能调出的内存,有虚拟分配的内存,还有实际使用的内存。

如果您更改代码以实际使用内存,例如只向分配的部分写入一个字节,您将看到完全不同的结果。 OS 必须处理内存分配并获取物理内存中的内存块。

另外如前所述,您没有检查 malloc 是否成功。也许它成功了几次,然后就不再分配任何东西了。

这个系统还解释了为什么有时一个进程可能会因为内存不足而被杀死,即使所有进程的所有分配都成功了。 OS 只是太乐观了,认为它可以提供比实际更多的内存。