如果`p`是`block *`类型,为什么`*(block **)p`与`block`不同? [CPython源代码]

时间:2019-01-26 04:26:25

标签: python c low-level

我正在尝试阅读一些CPython源代码,特别是obmalloc.chttps://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的代码。我的问题是:

  1. 这些任务如何工作?
  2. 我认为,如果*(block **)p的类型为pblock*应该是幂等的,为什么在这种情况下不是这样。
  3. 这似乎用于实现链表,该机制如何工作以及如何与*(block **)p相关?

1 个答案:

答案 0 :(得分:2)

代码是

pymalloc_free(void *ctx, void *p){
    ...
    *(block **)p = lastfree = pool->freeblock;
    pool->freeblock = (block *)p;
    ...
}

首先,blockuint8_t的typedef,即8位字节。它在这里仅用作语义标记,表示指针指向要分配的存储块,而不是任何随机字节或字符串。

您问:

  
      
  1. 我认为,如果*(block **)p的类型为pblock*应该是幂等的,为什么在这种情况下不是这样。
  2.   

不是,它将block *转换为block **,然后取消引用指针。请注意,在这种情况下,给定的指针是void *,而不是block *

  
      
  1. 这些任务如何工作?
  2.   

访问p指向的内存就像它指向 block *。而不是演员。如果有一个中间变量,因为它会使事情变得更加明显,那么会发生什么:

block **bpp = p
*bpp = lastfree = pool->freeblock;

bp = pool->freeblock;
block **bpp = bp;
if ((pool->freeblock = *bpp) != NULL) {
}
  
      
  1. 这似乎用于实现链表,该机制如何工作以及如何与*(block **)p相关?
  2.   

可用内存块都只是特定大小的字节块。空闲块的前sizeof (block *)(即sizeof (uint8_t *))个字节指向下一个字节块,因此可以将指向开始的指针转换为指向指针的指针,并取消引用以获取指针值位于前几个字节中。

请注意,该块还必须从_Alignof (block *)可以被pymalloc整除的地址开始。