在这种情况下如何进行内存分配? 我观察到这与在1000000 * 10000上直接使用malloc不同,这应该导致分配4 * 10GB(每个int 4个字节)。但是,这段代码在执行时仅使用200MB。
for(int i=0;i<1000000;i++)
{
int *A = (int*)malloc(sizeof(int)*10000);
}
答案 0 :(得分:2)
如上所述,内存是以块分配还是作为一个分配存在差异。您没有看到内存被分配的主要原因是操作系统存在内存。
如果您分配了一块内存,则分配为虚拟。由于所有进程都有大量可用的虚拟内存,因此通常会成功(除非您要求大量内存,否则操作系统会确定它无法正常工作)。实际使用内存后,可能会实际保留物理内存。
因此,当您查看内存使用情况时,不仅有一个数字,还有几个数字。存在共享存储器,存在无法被寻呼的存储器,存在虚拟分配的存储器,然后存在正在使用的实际存储器。
如果您将代码更改为实际使用内存,例如只将一个字节写入已分配的部分,您将看到完全不同的结果。操作系统必须处理内存分配并获取物理内存中的内存块。
同样如上所述,您不会检查malloc
是否成功。也许它会成功几次然后再分配任何东西。
该系统还解释了为什么有时一个进程可能因内存不足而被杀死,即使所有进程中的所有分配都成功。操作系统过于乐观,并认为它可以提供比实际可能更多的内存。
答案 1 :(得分:1)
区别在于如何分配内存。
当您拨打10k次malloc以分配10k内存时,会为您的进程分配10G虚拟内存。产生的10G内存不是连续。也就是说,你得到10k分散的内存块,其大小为10K。然而,当你调用malloc请求10G时,malloc将尝试分配一个大小为10G的连续内存块。
根据malloc手册页,malloc在无法分配请求的内存时失败。您应该检查malloc是否在您的应用程序中成功,以了解内存是否已正确分配。
答案 2 :(得分:1)
for(int i=0;i<1000000;i++)
{
int *A = (int*)malloc(sizeof(int)*10000);
}
这是内存泄漏的完美方式。您正在分配1000000
次,每次sizeof(int)*10000
个字节。您可以保证泄漏所有这些已分配的内存。当你在循环中声明A
时,所以在循环之后你不再拥有该变量的句柄,并且没有办法释放你分配的最后一块内存。
当然,这与一次性分配1000000*10000*sizeof(int)
不同。前者分配1000000
个较小的块,这些块主要散布在许多内存位置。后者试图分配一个巨大的块,这可能会失败。