! https://zhuanlan.zhihu.com/p/145953980
这章好硬盒啊,暂时有点啃不动,先写一点
为什么free()不知道内存长度就能准确释放内存?
其实就是问内存管理器,我明明没告诉你内存长度,你怎么能删除得这么准确呢?
老生常谈。从gdb调试的例子开始
1 #include <stdio.h>2 #include <stdlib.h>34 int main()5 {6 char * p1 = (char *)malloc(16);7 char * p2 = (char *)malloc(16);8 for(int i = 0; i < 16; i++)9 {10 p1[i] = (i + 1);11 p2[i] = (i + 1);12 }1314 printf("P1: %p, P2: %p\n", p1, p2);15 free(p1);16 free(p2);18 return 0;19 }
编译,GDB调试
Breakpoint 1, main () at memdemo.cpp:1414 printf("P1: %p, P2: %p\n", p1, p2);(gdb) p p1$1 = 0x602010 "\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020"(gdb) p p2$2 = 0x602030 "\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020"(gdb) x/16x 0x6020000x602000: 0x00000000 0x00000000 0x00000021 0x000000000x602010: 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d0x602020: 0x00000000 0x00000000 0x00000021 0x000000000x602030: 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d
可以看到,先是打印了p1,p2的内存地址,然后列出了从0x602000开始的地址。
很多人觉得奇怪,连续分配的内存,但是却没有紧挨在一起,中间都隔了16字节的内存,而且内容完全一样。
这是内存中的隐藏头技术,实际内存总要比你分配的大,一部分用来存储元信息。malloc好像是地址往前8字节划分为元信息,但是这个例子中却划分了16字节,可能这个是malloc分配的最小单位。
是注意倒着看, 0x00000000 0x00000021,这个就是内存的元信息。因为是内存以16字节为单位划分大小,所以最低四位没有意义(一次内存分配不可能小于16),也就是有意义的只有 0x2 也就是 32, 代表说实际一共分配了32字节,free的时候free这么多就行了。
其他待写
- brk和mmap
- 内存重释放,栈溢出,内存泄漏
