glibc&x27的内部运作;s free()
对于Glibc2.15,我在看malloc.c,特别是free()函数,对unlink()宏感到困惑。根据来源,正在使用的区块如下所示:glibc&x27的内部运作;s free(),c,heap,free,glibc,C,Heap,Free,Glibc,对于Glibc2.15,我在看malloc.c,特别是free()函数,对unlink()宏感到困惑。根据来源,正在使用的区块如下所示: chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Size of previous chunk, if allocated +-+-+-+-+-+-+-+-+-+-+-+
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Size of previous chunk, if allocated
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Size of chunk, in bytes
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
User data starts here... .
. .
. (malloc_usable_size() bytes) .
.
nextchunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Size of previous chunk
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' Size of chunk, in bytes
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Forward pointer to next chunk in list
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Back pointer to previous chunk in list
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Unused space (may be 0 bytes long) .
. .
.
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
一个free()'d块如下所示:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Size of previous chunk, if allocated
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Size of chunk, in bytes
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
User data starts here... .
. .
. (malloc_usable_size() bytes) .
.
nextchunk->+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Size of previous chunk
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' Size of chunk, in bytes
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Forward pointer to next chunk in list
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Back pointer to previous chunk in list
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Unused space (may be 0 bytes long) .
. .
.
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
当一个使用过的块是free()时,它将接收到的mem指针作为一个参数,并从中减去一个偏移量,得到一个块指针。在这两者之间有一系列的检查,但是在块没有被映射的情况下,它通常会向前或向后将其与另一个空闲块合并。因为chunk be free()'d已经在一个bin中,所以它只是在该bin中搜索要合并的chunk,对吗?在前向合并的情况下,将调用unlink()
宏,并将其应用于空闲块()后面的块。我不理解这一点,因为当下一个块(称为“nextchunk”)被取消链接时,会出现以下代码:
#define unlink(P, BK, FD) {
FD = P->fd;
BK = P->bk;
.
.
.
FD->bk = BK;
BK->fd = FD;
.
.
.
}
考虑到BK指向空闲的区块()'d,并且从其结构看,它没有向前或向后指针,如何引用
BK->fd
。我一定错过了代码中fd和bk字段添加到chunk being free()d的部分,但我不知道在哪里。有人能帮忙吗?谢谢。这一行在被释放的块中创建一个向前指针:
BK->fd = FD;
BK过去是一块用户数据,但现在是一块免费数据,因此允许malloc
在内存中随意涂鸦
如果有帮助,你可以把它想象成一个联盟:
union {
struct {
chunk *fd;
chunk *bk;
} freed;
unsigned char user_data[N];
};
在工会中,您可以向任何工会成员写信,但只能从最近写信的成员那里阅读。因此,当调用free
时,数据被写入fd
和bk
——这没关系,唯一的结果是user\u data
现在可能有垃圾。相比之下,当区块包含用户数据(非免费)时,fd
和bk
指针是垃圾,因为它们别名为user\u data
(从技术上讲,您始终可以读取用户\u数据
,不管它的别名是什么,因为它是无符号字符
,但这并不真正相关。)
更新:这是低级C代码。您希望在malloc
实现中使用低级C代码。字段存在或不存在的想法在低级代码中没有意义,因为我们在不同类型之间进行转换,并允许指针彼此别名
在低级代码中,字段只是内存偏移量。在我的系统上,fd
字段的偏移量可能为0,bk
字段的偏移量可能为8或4,具体取决于我编译的体系结构。因此,以下代码:
BK->fd = FD;
这意味着“将值FD写入存储器位置BK+0”。如果您认为BK->fd
只是内存中的一个位置,它可能会帮助您了解free
的工作原理。(它实际上不仅仅是内存中的一个位置,因为在编译时还存在类型信息和别名规则。)
理解低级C:如果您想理解低级C代码,那么理解汇编语言将非常有帮助。这不是必要的,但有帮助。学习哪种汇编语言并不重要:x86、MIPS、PowerPC、ARM等等。您不需要学习太多汇编语言,只需要一点点。您不需要学习x86,即使从未使用过MIPS,也可以学习MIPS。(事实上,MIPS可能更容易学习。)
只要学习足够多的汇编代码,就可以将一小段C代码翻译成汇编代码,这样就可以理解它在幕后做什么。上面的一行C代码可能会转换成一行汇编代码,因为它非常简单
在编写C时,尽量不要过多地考虑汇编。在编写C时,编译器编写汇编,这意味着您没有编写汇编。那么原来是malloc()的块的fd和bk字段是否正确?它们被标记为“用户数据”。但这是否意味着不能将任何数据写入用户数据的前x字节,以便fd和bk不会被覆盖?当区块被传递到
free
时,free
函数写入fd
和bk
字段。字段与用户数据重叠,但这没关系,因为用户数据不用于释放的块。但是,由于BK=nextchunk->BK BK BK BK BK是指向空闲块顶部的指针()'d,当调用BK->fd=fd时,这不只是“引用”吗字段fd或者它实际上是在BK中创建fd并将其设置为fd?Mabye我应该看看在调用malloc创建现在可用的内存时创建的初始结构。我确实了解x86程序集,并且理解代码中“存在”的概念,但是当引用了一个没有意义的偏移量时,这是行不通的。因此,当空闲的块()是malloc()'d时,它的结构必须在某个地方定义它…我将再次检查源代码.1+“当您编写C时,编译器正在编写程序集,这意味着您没有编写程序集。”