Почему `* (блок **) p` отличается от` block`, если `p` имеет тип` block * `?[Исходный код CPython] - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь прочитать часть исходного кода 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Мои вопросы:

  1. Как работают эти назначения?
  2. Я думал, что *(block **)p должен быть идемпотентным, если p имеет тип block*, почемуне в этом случае.
  3. Это, кажется, используется для реализации связанного списка, как этот механизм работает и как он связан с *(block **)p?

1 Ответ

0 голосов
/ 26 января 2019

Код

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

Прежде всего, block - это typedef для uint8_t, то есть 8-битный байт.Здесь он используется просто как семантический маркер, чтобы сказать, что указатель указывает на блок памяти для размещения вместо каких-либо случайных байтов где-либо или строки символов.

Вы спросили:

Я думал, что *(block **)p считается идемпотентным, если p имеет тип block*, почему нет в этом случае.

Это не такконвертирует block * в block ** и затем разыменовывает указатель.Обратите внимание, что в данном случае указатель является void *, а не block *.

  1. Как эти назначения работают?

доступ к памяти, на которую указывает p, осуществляется так, как если бы он указывал на a block *.Вместо слепков.Если бы существовала промежуточная переменная, потому что это сделало бы более очевидным, что происходит:

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

и

bp = pool->freeblock;
block **bpp = bp;
if ((pool->freeblock = *bpp) != NULL) {
}
Это, кажется, используется для реализации связанного списка, как этот механизм работает и как он связан с * (блок **) p?

Все свободные блоки памяти простокуски байтов определенного размера.Первые sizeof (block *) (т.е. sizeof (uint8_t *)) байтов свободного блока указывают на следующий блок байтов, поэтому указатель на начало может быть приведен к указателю на указатель и разыменован для получения this значение указателя находится в первых байтах.

Обратите внимание, что блок должен также начинаться с адреса, который делится на _Alignof (block *), который pymalloc тщательно поддерживает.

...