Linux堆结构和malloc()和free()的行为

sam*_*rai 5 c linux heap gdb memory-management

我有一个Debian的Linux 2.6内核,我试着去了解如何与堆工程/行为malloc()free().我试图搜索malloc()free()算法和堆结构,但我找不到任何有用的东西.不幸的是,我知道得少谈Linux和记忆是如何工作的,了解的源代码free()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);
}
Run Code Online (Sandbox Code Playgroud)

gdb,run AAAA BBBB CCCC我可以检查堆.这是在strcpys之前但之前的状态frees:

(gdb) x/32x 0x804c000
0x804c000:  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
Run Code Online (Sandbox Code Playgroud)

你可以看到char数组非常好.然后我试图找出为什么有0x29(dec 41).我期待像0x20(dec 32)或0x24(dec 36)这样的东西.

  • 为什么malloc算法浪费了这个空间?
  • 怎么决定它是0x29?
  • 最后的0xf89代表什么?
  • 该程序如何跟踪分配的内容和免费的内容?

特别是我想了解它的free()工作原理.在三次释放后,堆看起来像这样:

(gdb) x/32x 0x804c000
0x804c000:  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
Run Code Online (Sandbox Code Playgroud)
  • 为什么将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.
Run Code Online (Sandbox Code Playgroud)

我已经覆盖了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
Run Code Online (Sandbox Code Playgroud)

对我来说最重要的问题是:

  • 为什么在free()覆盖更多字节时会出现Segmentation故障?
  • free()算法如何工作?
  • 以及malloc和free如何跟踪地址?

非常感谢您的阅读,亲切的问候

dus*_*uff 9

大多数malloc()实现通过在分配的内存块之前和/或之后跟踪堆本身内的堆的状态来工作.超出已分配的块会导致此数据损坏 - 其中一些数据可能包含指针或长度,而破坏这些数据会导致实现尝试访问无效的内存位置.

malloc()实现如何工作的细节取决于您正在使用的系统和libc.如果你正在使用glibc(这可能是你在Linux上),那么它有一个非常好的解释:它在这里是如何工作的:

http://gee.cs.oswego.edu/dl/html/malloc.html

假设是这种情况,0x29您所看到的可能是块大小(32 = 0x20)和一些标志的按位OR .这是可能的,因为所有堆分配都舍入到最接近的16个字节(或更多!),因此大小的低8位始终可以假定为零.