我正在尝试一个不断分配内存的简单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]
答案 0 :(得分:6)
因为你在谈论/proc/pid/maps
我认为你是在Linux上。
这就是man malloc
告诉我关于我碰巧运行的linux发行版的内容:
通常,
malloc()
从堆中分配内存,并根据需要使用sbrk(2)
调整堆的大小。当分配大于
MMAP_THRESHOLD
字节的内存块时,glibcmalloc()
实现使用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()
调用似乎产生了这一点。
根据this,mmap()
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