Linux堆结构以及malloc()和free()的行为
我有一个带有Linux
2.6内核的Debian,我尝试了解堆如何与malloc()和一起工作free()。我试图寻找malloc()和free()算法和堆结构,但我无法找到任何有用的。不幸的是,我对Linux和内存的工作原理了解得很少,无法理解free()and
的源代码malloc()。
这是一个示例代码:
int main(int argc, char **argv){
    char *a, *b, *c;
    a = malloc(32);
    b = malloc(32);
    c = malloc(32);
    strcpy(a, argv[1]);
    strcpy(b, argv[2]);
    strcpy(c, argv[3]);
    free(c);
    free(b);
    free(a);
}
使用gdb和run AAAA BBBB CCCC我可以检查堆。这是,strcpys但之后的状态frees:
(gdb) x/32x 0x804c0000x804c000:  0x00000000  0x00000029  0x41414141  0x00000000
0x804c010:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c020:  0x00000000  0x00000000  0x00000000  0x00000029
0x804c030:  0x42424242  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c050:  0x00000000  0x00000029  0x43434343  0x00000000
0x804c060:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c070:  0x00000000  0x00000000  0x00000000  0x00000f89
您可以看到char数组非常好。然后,我试图找出为什么会有 (12月41日)。我期望像 (dec 32)或
(dec 36)之类的东西。
- 为什么malloc算法会 浪费 此空间?
 - 如何确定它是0x29?
 - 末尾的 代表什么?
 - 程序如何跟踪分配的内容和免费的内容?
 
我尤其想了解free()工作原理。在释放了三个之后,堆看起来像这样:
(gdb) x/32x 0x804c0000x804c000:  0x00000000  0x00000029  0x0804c028  0x00000000
0x804c010:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c020:  0x00000000  0x00000000  0x00000000  0x00000029
0x804c030:  0x0804c050  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c050:  0x00000000  0x00000029  0x00000000  0x00000000
0x804c060:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c070:  0x00000000  0x00000000  0x00000000  0x00000f89
- 为什么用此特定地址替换char数组?
 - 免费的伪代码是什么?
 
看这个例子:
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDDDD BBBB CCCC...
(gdb) x/32x 0x804c000
0x804c000:  0x00000000  0x00000029  0x41414141  0x41414141
0x804c010:  0x41414141  0x41414141  0x41414141  0x41414141
0x804c020:  0x41414141  0x41414141  0x44444444  0x00000044
0x804c030:  0x42424242  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c050:  0x00000000  0x00000029  0x43434343  0x00000000
0x804c060:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c070:  0x00000000  0x00000000  0x00000000  0x00000f89
...
(gdb) c
Program exited with code 021.
我已经覆盖了0x29,但是程序正常退出。但是,当我添加另一个字节时,我遇到了分段错误:
(gdb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDDDD BBBB CCCC...
(gdb) x/32x 0x804c000
0x804c000:  0x00000000  0x00000029  0x41414141  0x41414141
0x804c010:  0x41414141  0x41414141  0x41414141  0x41414141
0x804c020:  0x41414141  0x41414141  0x44444444  0x00004444
0x804c030:  0x42424242  0x00000000  0x00000000  0x00000000
0x804c040:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c050:  0x00000000  0x00000029  0x43434343  0x00000000
0x804c060:  0x00000000  0x00000000  0x00000000  0x00000000
0x804c070:  0x00000000  0x00000000  0x00000000  0x00000f89
...
(gdb) c
Program received signal SIGSEGV, Segmentation fault.
0x080498b9 in free (mem=0x804c030) at common/malloc.c:3631
对我来说最重要的问题是:
free()当覆盖更多字节时,为什么会出现分段错误?- 以及该
free()算法如何工作? - 以及malloc和free如何跟踪地址?
 
非常感谢您的阅读,亲切的问候
回答:
大多数malloc()实现都是通过在分配的内存块之前和/或之后跟踪堆自身内部的堆状态来工作的。超出分配的块会导致此数据被破坏-
其中一些数据可能包含指针或长度,而破坏这些数据会导致实现尝试访问无效的内存位置。
实现方式的详细信息malloc()取决于您所使用的系统和libc。如果您使用的是glibc(如果您使用的是Linux,则可能会出现这种情况),此处对此有一个很好的解释:
http://gee.cs.oswego.edu/dl/html/malloc.html
假设情况如此,0x29您看到的可能是块大小(32 =
0x20)和一些标志的按位或。这是可能的,因为所有堆分配都舍入到最接近的16个字节(或更多!),因此可以始终假定大小的低八位为零。
以上是 Linux堆结构以及malloc()和free()的行为 的全部内容, 来源链接: utcz.com/qa/404729.html

