Malloc& calloc:分配的内存大小不同

时间:2015-12-01 14:55:19

标签: c memory memory-management malloc calloc

所以,我有这段代码:

#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测试)

1 个答案:

答案 0 :(得分:2)

查看程序输出,实际上为65188分配了相同数量的块,malloc65189分配calloc。忽略开销,这个内存略小于2GB。

我的猜测是你在32位模式下编译(指针被转储为32位),这将单个用户进程可用的内存量限制为小于2GB。流程图显示的差异来自程序如何使用它分配的内存。

malloc版本未触及已分配的页面:超过四分之三的版本未实际映射,因此 430MB。

calloc版本显示2GB 映射内存:您的C库函数calloc可能会清除已分配的内存,即使对于从操作系统获取的页面也是如此。这不是最佳选择,但只有在您不触摸分配的内存时才可见,无论如何都是特殊情况。然而,不清除从OS获得的页面会更快,因为它们被指定为零填充。

在Linux中,您可能正在编译为64位,可以访问超过2GB的虚拟进程空间。由于你没有触摸内存,因此它没有被映射,同样在calloc情况下也是如此。 C运行时不同(Linux上为64位glibc,Windows上为32位Microsoft库)。您应该在Linux的不同终端中使用topps来检查在两种情况下实际映射到您的进程的内存量。