所以,我有这段代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
long n = 1;
while(1) {
p = malloc(n * sizeof(char));
//p = calloc(n, sizeof(char));
if(p) {
printf("[%ld] Memory allocation successful! Address: %p\n", n , p);
n++;
} else {
printf("No more memory! Sorry...");
break;
}
}
free(p);
getch();
return 0;
}
我在Windows上运行。有趣的事情:
如果我们使用malloc,程序会分配大约430 MB的内存,然后停止(照片在这里=&gt; http://i.imgur.com/woswThG.png)
如果我们使用calloc,程序会分配大约2 GB的内存然后停止(照片在这里=&gt; http://i.imgur.com/3JKy5pA.png)
(奇怪的测试):如果我们同时使用它们两者,它使用最大值(~400MB + ~2GB)/ 2 =&gt; 〜1.2GB
但是,如果我在Linux上运行相同的代码,分配会继续进行(在600k分配之后,许多GB使用它仍然会一直持续到最终被杀死)并且使用大约相同的内存量。
所以我的问题是:他们不应该分配相同数量的内存吗?我认为唯一的区别是calloc用零初始化内存(malloc返回未初始化的内存)。为什么它只发生在Windows上?同时这很奇怪也很有趣。
希望你能帮我解释一下。谢谢!
编辑:
Code :: Blocks 13.12 with GNU GCC Compiler
Windows 10(x64)
Linux Mint 17.2“Rafaela” - Cinnamon(64位)(用于Linux测试)
答案 0 :(得分:2)
查看程序输出,实际上为65188
分配了相同数量的块,malloc
,65189
分配calloc
。忽略开销,这个内存略小于2GB。
我的猜测是你在32位模式下编译(指针被转储为32位),这将单个用户进程可用的内存量限制为小于2GB。流程图显示的差异来自程序如何使用它分配的内存。
malloc
版本未触及已分配的页面:超过四分之三的版本未实际映射,因此仅 430MB。
calloc
版本显示2GB 映射内存:您的C库函数calloc
可能会清除已分配的内存,即使对于从操作系统获取的页面也是如此。这不是最佳选择,但只有在您不触摸分配的内存时才可见,无论如何都是特殊情况。然而,不清除从OS获得的页面会更快,因为它们被指定为零填充。
在Linux中,您可能正在编译为64位,可以访问超过2GB的虚拟进程空间。由于你没有触摸内存,因此它没有被映射,同样在calloc
情况下也是如此。 C运行时不同(Linux上为64位glibc
,Windows上为32位Microsoft库)。您应该在Linux的不同终端中使用top
或ps
来检查在两种情况下实际映射到您的进程的内存量。