0
点赞
收藏
分享

微信扫一扫

58 多次基于 malloc 分配内存的一些现象分析


问题来自于文章 内存分配的小例子请教

内存分配的小例子请教 - 内核源码-Chinaunix

 

本文的内容, 如果您有阅读, 如下文章 应该还是很好理解, 建议先阅读如下文章 

malloc 虚拟内存分配的调试(1)

malloc 虚拟内存分配的调试(2)

printf 的调试

 

 

测试用例

主题是这一系列 malloc 

#include<stdio.h>

int main(int argc, char **argv) {

    void *p, *p1, *p2, *p3, *p4, *p5, *p6, *p7;

    printf(" sbrk(0) is 0x%02x \n", sbrk(0));

    p = malloc(1024);
    printf(" sbrk(0) is 0x%02x after malloc  \n", sbrk(0));

    p1 = malloc(2 * 1024);
    p2 = malloc(4 * 1024);
    p3 = malloc(8 * 1024);
    p4 = malloc(16 * 1024);
    p5 = malloc(32 * 1024);
    p6 = malloc(64 * 1024);
    p7 = malloc(128 * 1024);

    printf(" p is 0x%02x  \n", p);
    printf(" p1 is 0x%02x, p2 is 0x%02x, p3 is 0x%02x  \n", p1, p2, p3);
    printf(" p4 is 0x%02x, p5 is 0x%02x, p6 is 0x%02x  \n", p4, p5, p6);
    printf(" p7 is 0x%02x  \n", p7);

    printf(" sbrk(0) is 0x%02x at final  \n", sbrk(0));

    return 0;

}

 

  1. 为什么 p1 和 p0 差 1040, 而不是 1024
  2. 为什么 p7 malloc 128K 后地址是在远端 0xf7fcd010
  3. 为什么一系列 malloc 之后 brk 依然在 0x623000
  4. 反应伙伴系统的分配策略?

 

执行结果如下 

root@ubuntu:~/linux/tmp# ./Test15MallocManyTimes
 sbrk(0) is 0x602000
 sbrk(0) is 0x623000 after malloc
 p is 0x602420
 p1 is 0x602830, p2 is 0x603040, p3 is 0x604050
 p4 is 0x606060, p5 is 0x60a070, p6 is 0x612080
 p7 is 0xf7fcd010
 sbrk(0) is 0x623000 at final

 

 

strace 执行观察系统调用日志如下

root@ubuntu:~/linux/tmp# strace ./Test15MallocManyTimes
execve("./Test15MallocManyTimes", ["./Test15MallocManyTimes"], [/* 23 vars */]) = 0
brk(NULL)                               = 0x602000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=25854, ...}) = 0
mmap(NULL, 25854, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ffff7ff1000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\t\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7ff0000
mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ffff7a0d000
mprotect(0x7ffff7bcd000, 2097152, PROT_NONE) = 0
mmap(0x7ffff7dcd000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7ffff7dcd000
mmap(0x7ffff7dd3000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffff7dd3000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fef000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fee000
arch_prctl(ARCH_SET_FS, 0x7ffff7fef700) = 0
mprotect(0x7ffff7dcd000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7ffff7ffc000, 4096, PROT_READ) = 0
munmap(0x7ffff7ff1000, 25854)           = 0
brk(NULL)                               = 0x602000
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
brk(0x623000)                           = 0x623000
write(1, " sbrk(0) is 0x602000 \n", 22 sbrk(0) is 0x602000
) = 22
write(1, " sbrk(0) is 0x623000 after mallo"..., 36 sbrk(0) is 0x623000 after malloc
) = 36
mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ffff7fcd000
write(1, " p is 0x602420  \n", 17 p is 0x602420
)      = 17
write(1, " p1 is 0x602830, p2 is 0x603040,"..., 50 p1 is 0x602830, p2 is 0x603040, p3 is 0x604050
) = 50
write(1, " p4 is 0x606060, p5 is 0x60a070,"..., 50 p4 is 0x606060, p5 is 0x60a070, p6 is 0x612080
) = 50
write(1, " p7 is 0xf7fcd010  \n", 20 p7 is 0xf7fcd010
)   = 20
write(1, " sbrk(0) is 0x623000 at final  \n", 32 sbrk(0) is 0x623000 at final
) = 32
exit_group(0)                           = ?
+++ exited with 0 +++

 

 

为什么 p1 和 p0 差 1040, 而不是 1024

p 占用的空间 (0x602830 - 0x602420) = 0x410 = 1040

因为还有 8 字节的头部, 加上对齐 比 (1024 + 8) 大的最小的 16 的倍数为 1040

具体的计算方式为 (1024 + 8 + 15) & 0xfffffff0 = 1040

 

 

为什么 p7 malloc 128K 后地址是在远端 0xf7fcd010

malloc 在申请空间大于 128kb 的时候 会调用 mmap 进行申请空间

因此 p7 是在 mmap 映射区 

 

 

为什么一系列 malloc 之后 brk 依然在 0x623000

因为第一次 malloc 合计申请了 132kb 的空间 

足以容纳下 p – p6, 因此 p – p6 均是在 malloc 申请的第一块空间中 

 

 

反应伙伴系统的分配策略?

伙伴系统的反应是在 申请了虚拟内存之后 使用的时候 产生缺页中断的时候 才会体现

这个对 业务代码来说是透明的

 

 

brk 的基地址 和 mmap映射区的基地址

brk 的基地址 和 mmap映射区的基地址 和 地址随机化有关系 

开启策略之后 地址可能会随机变化

 

brk 初始的地方到 p 还有一段空间是 printf 的缓冲区 

 

 

 

 

 

举报

相关推荐

0 条评论