ls0f / my-issues

0 stars 0 forks source link

malloc VS calloc #28

Open ls0f opened 8 years ago

ls0f commented 8 years ago

据我理解:calloc会将申请的所有内存bit设置0,然后我在Mac上用malloc和calloc测试申请内存:

#include <stdio.h>
#include <stdlib.h>
#include<string.h>

int main (void) {
        int n = 0;
        char *p;
        while (1) {
                if ((p=malloc(1<<20)) == NULL) {
                        printf("malloc failure after %d MiB\n", n);
                        return 0;
                }
                //memset (p, 0, (1<<20));
                printf ("got %d MiB\n", ++n);
        }
}

如果注释掉memset,循环直到出现下面的错误:

ex(79659,0x7fff7571e000) malloc: *** mach_vm_map(size=67108864) failed (error code=3)
error: can't allocate region
set a breakpoint in malloc_error_break to debug

calloc和malloc都是这样。 启用memset的话,可以申请60G左右,程序实际占有内存大概是4G左右,然后会被内核kill掉。

malloc申请内存块,通常只有在使用的时候内核才会分配物理页面(会占用少量内存记录相关信息),只要不使用一直可以申请下去,直到超出虚拟内存寻址范围或者out of memory,这个可以理解。但是calloc会将内存的每个bit都设置为0,这个就相当于使用了内存,为什么效果还是会和malloc一样呢?难道使用calloc内核也并没有分配物理页面?

后来我在这个问题下面找到了答案。why-mallocmemset-is-slower-than-calloc

当你申请内存的时候,并不会马上向内核申请物理内存页面,这样效率太慢,只会在实际使用的时候才会申请物理内存页和执行初始化,而memset是强制内核分配物理内存页,将所有bit设置为0,

The "calloc" implementation just changes a few page tables, consumes very little actual memory, writes to very little memory, and returns. On most systems you can even allocate more memory than your system can support (more than RAM + swap) without problems, as long as you don't write to all of it. (This feature is slightly controversial on the operating systems that allow this.)

这篇文章也给了很详细的解释。

http://opsmonkey.blogspot.jp/2007/01/linux-memory-overcommit.html http://www.win.tue.nl/~aeb/linux/lk/lk.html#toc9 http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc/2688522#2688522 http://unix.stackexchange.com/questions/149771/malloc-and-paging http://www.etalabs.net/overcommit.html