在这种情况下,内存分配是如何发生的?我观察到这与直接在 1000000*10000 上使用 malloc 不同,这应该会导致分配 4*10GB(每个整数 4 个字节(。但是,这段代码在执行时仅使用 200MB。
for(int i=0;i<1000000;i++)
{
int *A = (int*)malloc(sizeof(int)*10000);
}
如前所述,内存是按块分配还是作为一个块分配存在差异。您没有看到正在分配的内存的主要原因是由于操作系统在内存上撒谎。
如果分配内存块,则分配是虚拟的。由于所有进程都有大量可用的虚拟内存,因此它通常会成功(除非您要求疯狂的内存量,或者操作系统以其他方式确定它不会工作(。实际使用内存后,可能会发生物理内存的实际预留。
因此,当您查看内存使用情况时,不仅有一个数字,而且有几个数字。有共享内存,有无法分页的内存,有虚拟分配的内存,然后是正在使用的实际内存。
如果您更改代码以实际使用内存,例如只需将一个字节写入分配的部分,您将看到完全不同的结果。操作系统必须处理内存分配并获取物理内存中的内存块。
另外,如前所述,您不会检查malloc
是否成功。也许它成功了几次,然后不再分配任何东西。
此系统还解释了为什么有时即使所有进程中的所有分配都成功,进程也可能由于内存不足而被终止。操作系统只是过于乐观,认为它可以提供比实际可能更多的内存。
区别在于内存的分配方式。
当您调用 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
字节。您一定会泄漏所有这些分配的内存。正如您在循环中声明A
的那样,因此在循环之后,您不再拥有该变量的句柄,甚至无法释放您分配的最后一块内存。
当然,这与一次性分配1000000*10000*sizeof(int)
是不同的。前者分配1000000
较小的块,这些块主要分散在许多内存位置。后者试图分配一个巨大的块,这可能会失败。