Malloc & calloc:分配不同的内存大小
Malloc & calloc: different memory size allocated
所以,我有这段代码:
#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 的内存然后停止(照片在这里 => http://i.imgur.com/woswThG.png)
如果我们使用 calloc,程序会分配大约 2 GB 的内存然后停止(照片在这里 => http://i.imgur.com/3JKy5pA.png)
(奇怪的测试):如果我们同时使用它们,它最多使用 (~400MB + ~2GB) / 2 => ~1.2GB
但是,如果我 运行 在 Linux 上使用相同的代码,分配将继续进行(在 600k 分配和许多 GB 使用后它仍然继续直到最终被杀死)并且大约使用相同数量的内存。
所以我的问题是:他们不应该分配相同数量的内存吗?我认为唯一的区别是 calloc 用零初始化内存(malloc returns 未初始化的内存)。为什么它只发生在 Windows?既奇怪又有趣。
希望你能帮我解释一下。谢谢!
编辑:
Code::Blocks 13.12 与 GNU GCC 编译器
Windows 10 (x64)
Linux Mint 17.2 "Rafaela" - Cinnamon(64 位)(用于 Linux 测试)
查看程序输出,您实际上分配了相同数量的块,65188
用于 malloc
,65189
用于 calloc
。忽略开销,这略小于 2GB 内存。
我的猜测是您在 32 位模式下编译(指针被转储为 32 位),这将单个用户进程可用的内存量限制在 2GB 以下。进程图显示的不同之处在于您的程序如何使用它分配的内存。
malloc
版本不涉及分配的页面:其中超过四分之三的页面实际上没有映射,因此只有 430MB。
calloc
版本显示 2GB 的 mapped 内存:您的 C 库函数 calloc
可能会清除分配的内存,即使对于从OS。这不是最佳的,但只有在您不触摸分配的内存时才可见,无论如何都是一种特殊情况。然而,不清除从 OS 获得的页面会更快,因为它们被指定为零填充。
在 Linux 中,您可能正在编译为 64 位,可以访问超过 2GB 的虚拟进程 space。由于您没有触及内存,因此它没有被映射,在 calloc
情况下似乎也会发生同样的情况。 C 运行时不同(64 位 glibc
在 Linux 上,32 位 Microsoft 库在 Windows 上)。您应该在 Linux 的不同终端中使用 top
或 ps
来检查在这两种情况下实际映射到您的进程的内存量。
所以,我有这段代码:
#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 的内存然后停止(照片在这里 => http://i.imgur.com/woswThG.png)
如果我们使用 calloc,程序会分配大约 2 GB 的内存然后停止(照片在这里 => http://i.imgur.com/3JKy5pA.png)
(奇怪的测试):如果我们同时使用它们,它最多使用 (~400MB + ~2GB) / 2 => ~1.2GB
但是,如果我 运行 在 Linux 上使用相同的代码,分配将继续进行(在 600k 分配和许多 GB 使用后它仍然继续直到最终被杀死)并且大约使用相同数量的内存。
所以我的问题是:他们不应该分配相同数量的内存吗?我认为唯一的区别是 calloc 用零初始化内存(malloc returns 未初始化的内存)。为什么它只发生在 Windows?既奇怪又有趣。
希望你能帮我解释一下。谢谢!
编辑:
Code::Blocks 13.12 与 GNU GCC 编译器
Windows 10 (x64)
Linux Mint 17.2 "Rafaela" - Cinnamon(64 位)(用于 Linux 测试)
查看程序输出,您实际上分配了相同数量的块,65188
用于 malloc
,65189
用于 calloc
。忽略开销,这略小于 2GB 内存。
我的猜测是您在 32 位模式下编译(指针被转储为 32 位),这将单个用户进程可用的内存量限制在 2GB 以下。进程图显示的不同之处在于您的程序如何使用它分配的内存。
malloc
版本不涉及分配的页面:其中超过四分之三的页面实际上没有映射,因此只有 430MB。
calloc
版本显示 2GB 的 mapped 内存:您的 C 库函数 calloc
可能会清除分配的内存,即使对于从OS。这不是最佳的,但只有在您不触摸分配的内存时才可见,无论如何都是一种特殊情况。然而,不清除从 OS 获得的页面会更快,因为它们被指定为零填充。
在 Linux 中,您可能正在编译为 64 位,可以访问超过 2GB 的虚拟进程 space。由于您没有触及内存,因此它没有被映射,在 calloc
情况下似乎也会发生同样的情况。 C 运行时不同(64 位 glibc
在 Linux 上,32 位 Microsoft 库在 Windows 上)。您应该在 Linux 的不同终端中使用 top
或 ps
来检查在这两种情况下实际映射到您的进程的内存量。