当前位置: 首页 > 面试题库 >

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

景星光
2023-03-14
问题内容

我有一个带有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);
}

使用gdbrun 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

您可以看到char数组非常好。然后,我试图找出为什么会有 0x29 (12月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
  • 为什么用此特定地址替换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个字节(或更多!),因此可以始终假定大小的低八位为零。



 类似资料:
  • 问题内容: 我是Go的新手,在C风格的基于堆栈的编程(其中自动变量位于堆栈上,分配的内存位于堆中)与Python风格的基于堆栈的编程(其中唯一存在于堆栈中的东西是对堆上对象的引用/指针。 据我所知,以下两个函数给出的输出相同: 即分配一个新的结构并返回它。 如果用C编写,第一个将对象放到堆上,第二个将对象放到堆栈上。第一个将返回指向堆的指针,第二个将返回指向堆栈的指针,该指针将在函数返回时消失,这

  • 条款3:尽量用new和delete而不用malloc和free malloc和free(及其变体)会产生问题的原因在于它们太简单:他们不知道构造函数和析构函数。 假设用两种方法给一个包含10个string对象的数组分配空间,一个用malloc,另一个用new:    string *stringarray1 = static_cast<string*>(malloc(10 * sizeof(st

  • 更多面试题总结请看:【面试题】技术面试题汇总 malloc / free 简介 void *malloc(size_t size) void free(void *ptr) malloc 分配指定大小的内存空间,返回一个指向该空间的指针。大小以字节为单位。返回 void* 指针,需要强制类型转换后才能引用其中的值。 free 释放一个由 malloc 所分配的内存空间。ptr 指向一个要释放内存

  • 预备条件: 理解 glibc malloc 从 2004 年末开始,glibc malloc 变得更可靠了。之后,类似 unlink 的技巧已经废弃,攻击者没有线索。但是在 2005 年末,Phantasmal Phatasmagoria 带来了下面这些技巧,用于成功利用堆溢出。 House of Prime House of Mind House of Force House of Lore H

  • 问题内容: 我从来没有见过这样的声明,它是否存在于Java世界中? 问题答案: Java的版本是-它创建指定类型的新对象。 在Java中,内存是为您管理的,因此您不能显式或对象。

  • 本文向大家介绍linux用户组以及权限总结,包括了linux用户组以及权限总结的使用技巧和注意事项,需要的朋友参考一下 用户组 在linux 中每个用户必须属于一个组,而Linux下有三种组的概念,如下: 文件所拥有者 用户所在组 其他组 文件所有者: 就是文件的创造者,谁创建的文件,谁就是文件的所有者。 用户所在组: 当Linux当前用户创建了一个文件后,则这个文件所属于的组便是这个用户所在的组