В чем разница между & address + sizeof (тип) и & address + 1? - PullRequest
0 голосов
/ 14 декабря 2018

Я пытаюсь перекодировать функцию malloc.
Давайте представим, что у нас есть такая структура:

typedef struct      s_block
{
    char            is_free;
    size_t          size;
    struct s_block  *next;
    void            *memory;
}                   t_block;

Я выделяю страницу памяти с помощью mmap, и я преобразую ее вbig t_block.
Затем у меня есть 1 блок размером 4064 (4096 - размер t_block).
Если я назову свой malloc, например, размером 12, вот что я делаю:

block->next = &block + 1 + size // Setting the next block
block->next->size = block->size - size - sizeof(t_block); // 4064 - 12 - 32
block->size = size; // 12
block->is_free = NOT_FREED;
block->memory = &block + 1;
block->next->memory = &(block->next) + 1;
block->next->next = NULL;
block->next->is_free = FREE;

У меня часто возникают проблемы, когда я использую + 1 или + sizeof (t_block).Итак, в чем разница между:

block->next = &block + 1 + size;

и:

block->next = &block + sizeof(t_block) + size;

?

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Предполагая, что block объявлено как t_block * и что вы хотите size байтов между этим блоком и следующим, ни то, ни другое не соответствует ожидаемому.Поскольку &block является адресом указателя, любая арифметика указателя, выполненная на нем, работает на основе размера указателя, а не размера структуры.

То, что вы на самом деле хотите:

block->next = (t_block *)((char *)block + sizeof(t_block) + size);

При первом приведении block к char * любая арифметика указателей, выполненная на нем, работает с одиночными байтами, а не с кратным размером структуры.Итак, мы начинаем с адреса блока, перемещаемся вверх sizeof(t_block) байтов к началу памяти пользователя, затем size больше байтов к концу этой памяти и началу следующего блока.

Кроме того, из-за требований к выравниванию вашей структуры вам необходимо убедиться, что следующий блок выровнен правильно.Вы можете сделать это следующим образом:

size_t block_align = (sizeof(t_block) - (size % sizeof(t_block))) % sizeof(t_block);
block->next = (t_block *)((char *)block + sizeof(t_block) + block_align + size);
0 голосов
/ 14 декабря 2018

((Type*)(p)) + n == ((char*)(p)) + sizeof(Type)*n

Арифметика (то есть просто сложение / вычитание) для типизированных указателей масштабируется по размеру указательного типа (sizeof(char) определяется как 1).

...