我正在尝试阅读一些CPython源代码,特别是obmalloc.c
(https://github.com/python/cpython/blob/master/Objects/obmalloc.c)。当我阅读与malloc和自由工作等效的内容时,我想到了以下几行:
pymalloc_free(void *ctx, void *p){
...
*(block **)p = lastfree = pool->freeblock;
pool->freeblock = (block *)p;
...
}
和
pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes){
bp = pool->freeblock;
if ((pool->freeblock = *(block **)bp) != NULL) {
...
}
...
}
此处块为typedef uint8_t block;
,pool
结构为:
struct pool {
...
block *freeblock;
...
}
我无法理解所有使用*(block **)p
的代码。我的问题是:
*(block **)p
的类型为p
,block*
应该是幂等的,为什么在这种情况下不是这样。*(block **)p
相关?答案 0 :(得分:2)
代码是
pymalloc_free(void *ctx, void *p){
...
*(block **)p = lastfree = pool->freeblock;
pool->freeblock = (block *)p;
...
}
首先,block
是uint8_t
的typedef,即8位字节。它在这里仅用作语义标记,表示指针指向要分配的存储块,而不是任何随机字节或字符串。
您问:
- 我认为,如果
*(block **)p
的类型为p
,block*
应该是幂等的,为什么在这种情况下不是这样。
不是,它将block *
转换为block **
,然后取消引用指针。请注意,在这种情况下,给定的指针是void *
,而不是block *
。
- 这些任务如何工作?
访问p
指向的内存就像它指向 block *
。而不是演员。如果有一个中间变量,因为它会使事情变得更加明显,那么会发生什么:
block **bpp = p
*bpp = lastfree = pool->freeblock;
和
bp = pool->freeblock;
block **bpp = bp;
if ((pool->freeblock = *bpp) != NULL) {
}
- 这似乎用于实现链表,该机制如何工作以及如何与*(block **)p相关?
可用内存块都只是特定大小的字节块。空闲块的前sizeof (block *)
(即sizeof (uint8_t *)
)个字节指向下一个字节块,因此可以将指向开始的指针转换为指向指针的指针,并取消引用以获取该指针值位于前几个字节中。
请注意,该块还必须从_Alignof (block *)
可以被pymalloc
整除的地址开始。