缺少/ proc / pid / maps中的[heap]部分

时间:2013-07-22 07:59:28

标签: c memory

我正在尝试一个不断分配内存的简单C程序:

for ( i = 0; i < 10000; i ++ )
{
    array[i] = malloc( 1024*1024 );
    if ( array[i] == NULL )
    {
        break;
    }
    printf("Sleeping...%d\n", i);
    sleep( 60 );
}

此处粘贴完整代码:http://tny.cz/2d9cb3df

但是,当我cat /proc/pid/maps时,我没有[heap]部分。为什么呢?

08048000-08049000 r-xp 00000000 08:11 17         /data/a.out
08049000-0804a000 r--p 00000000 08:11 17         /data/a.out
0804a000-0804b000 rw-p 00001000 08:11 17         /data/a.out
0804b000-0805e000 rw-p 00000000 00:00 0 
b74c6000-b75c8000 rw-p 00000000 00:00 0 
b75c8000-b7775000 r-xp 00000000 08:01 3539272    /lib/i386-linux-gnu/libc-2.17.so
b7775000-b7777000 r--p 001ad000 08:01 3539272    /lib/i386-linux-gnu/libc-2.17.so
b7777000-b7778000 rw-p 001af000 08:01 3539272    /lib/i386-linux-gnu/libc-2.17.so
b7778000-b777b000 rw-p 00000000 00:00 0 
b7797000-b779a000 rw-p 00000000 00:00 0 
b779a000-b779b000 r-xp 00000000 00:00 0          [vdso]
b779b000-b77bb000 r-xp 00000000 08:01 3539289    /lib/i386-linux-gnu/ld-2.17.so
b77bb000-b77bc000 r--p 0001f000 08:01 3539289    /lib/i386-linux-gnu/ld-2.17.so
b77bc000-b77bd000 rw-p 00020000 08:01 3539289    /lib/i386-linux-gnu/ld-2.17.so
bff21000-bff42000 rw-p 00000000 00:00 0          [stack]

3 个答案:

答案 0 :(得分:6)

因为你在谈论/proc/pid/maps我认为你是在Linux上。

这就是man malloc告诉我关于我碰巧运行的linux发行版的内容:

  

通常,malloc()从堆中分配内存,并根据需要使用sbrk(2)调整堆的大小。

     

当分配大于MMAP_THRESHOLD字节的内存块时,glibc malloc()实现使用mmap(2)将内存分配为私有匿名映射。 MMAP_THRESHOLD默认为128 kB,但可以使用mallopt(3)进行调整。

     

使用mmap(2)执行的分配不受RLIMIT_DATA资源限制的影响(请参阅getrlimit(2))。

如果您真的希望[heap]中的/proc/pid/maps每次调用malloc时分配的内容少于128k。

答案 1 :(得分:1)

上述部分并未声明为“堆”,因为它是通过mmap()来电分配的。

在我的64位系统上,分配的内存来自这个不断增长的部分:

7f7fbda7a000-7f7fbdc7c000 rw-p 00000000 00:00 0
...
7f7fbc868000-7f7fbdc7c000 rw-p 00000000 00:00 0
...
7f7fbc363000-7f7fbdc7c000 rw-p 00000000 00:00 0

该部分在开始时被扩展,新分配的内存总是起始地址+ 0x10。

内存分配器在这里做的是

mmap(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7fbb353000

奇怪的事;我怀疑每个mmap()内存部分是单独显示的。但是,如果我让程序执行中间free()调用,则内存分配如下:

7f16be944000-7f16bec47000 rw-p 00000000 00:00 0
7f16bed48000-7f16bee49000 rw-p 00000000 00:00 0

在其他连续记忆中已经出现了漏洞。

还有一件事情发生了:在这个修改过的程序中,确实存在[heap]部分。由于重新出现超出我的理解,该程序开始通过brk()分配,这是(可能)堆来自的地方:

每次调用brk()时,相应的部分都会在其末尾扩展:

01183000-029a4000 rw-p 00000000 00:00 0                                  [heap]

我不知道malloc()改变分配的“真正”堆(连接到brk()的东西)的想法已经改变了。与相应的munmap()相关的第一个free()调用似乎产生了这一点。

根据thismmap() ed块似乎有最大值。如果超过此值,gnulibc将回退到brk() / sbrk(),它在“常规堆区域”上运行。

因此,答案较短:从malloc()获取的brk()内存位于“真实”[heap]部分,mmap()内存部分未标记为[heap]

答案 2 :(得分:0)

使用brk()调用进行动态分配。在程序加载期间计算.brk部分的开头(查看/linux/fs/binfmt_elf.c中的load_elf_binary())。但是,在请求实际分配的运行时期间,页面不会映射。请参阅下面在x86_64系统上分配之前和之后的/ proc / pid / maps的屏幕显示

在调用calloc(8032,1)之前:

$ cat /proc/$(pid)/maps

00400000-00401000 r-xp 00000000 08:02 1314308             /testheap

00600000-00601000 r--p 00000000 08:02 1314308             /testheap

00601000-00602000 rw-p 00001000 08:02 1314308             /testheap

7fafeea3e000-7fafeebfb000 r-xp 00000000 08:02 198420      /lib/x86_64-linux-gnu/libc-2.17.so

7fafeebfb000-7fafeedfb000 ---p 001bd000 08:02 198420      /lib/x86_64-linux-gnu/libc-2.17.so

调用calloc(8032,1)后:

$cat /proc/$(pid)/maps

00400000-00401000 r-xp 00000000 08:02 1314308             /testheap

00600000-00601000 r--p 00000000 08:02 1314308             /testheap

00601000-00602000 rw-p 00001000 08:02 1314308             /testheap

**021ea000-0220c000 rw-p 00000000 00:00 0                   [heap]**

7fafeea3e000-7fafeebfb000 r-xp 00000000 08:02 198420      /lib/x86_64-linux-gnu/libc-2.17.so

7fafeebfb000-7fafeedfb000 ---p 001bd000 08:02 198420      /lib/x86_64-linux-gnu/libc-2.17.so