Восстановить значение, установленное memset

Как я могу восстановить значение memset?

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

void* my_malloc(size_t sz)
    void* block = malloc(sz + sizeof(size_t));
    void* retval = &block + sizeof(size_t);
    memset(block, sz, sizeof(size_t));
return retval;

В другой функции пользователь может передать указатель на свои данные, и я хочу восстановить размер, который я сохранил перед своей памятью.

void my_free(void *ptr) {

    void* block = ptr - sizeof(size_t);
    size_t *sz;
    memset(sz, block, sizeof(size_t));//This is the line in question.

free(block);

Есть ли какая-либо функция memread, я могу использовать сброс значения sz? Этот текущий метод дает мне ошибки

1 ответ

Решение

Вам действительно нужно прочитать документацию memset, Он устанавливает блок памяти, чтобы все байты были одинаковыми. Эффект memset(block, sz, sizeof(size_t)) это установить первый 8 (или любой другой размер size_t is) байтов block всем быть (unsigned char)sz,

Чтобы скопировать несколько байтов, правильная функция memcpyтак что строка должна быть:

memcpy(block, &sz, sizeof sz);

в free функция, которую вы хотите:

size_t sz;
memcpy(&sz, block, sizeof sz);

Кроме того, вы делаете неверную арифметику указателей в двух местах:

void *retval = &block + sizeof(size_t);    // moves sizeof(size_t) * sizeof(void *) bytes
void *block = ptr - sizeof(size_t);        // illegal

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

void *retval = (char *)block + sizeof(size_t);
void *block = (char *)ptr - sizeof(size_t);

Приведение происходит потому, что арифметика указателя не определена для void *, поскольку sizeof(char) == 1 затем делать арифметику указателя на char * перемещает вас на это количество байтов.

Если вы правильно понимаете арифметику указателей, вы поймете, что другой способ написания этих операторов:

void *retval = (size_t *)block + 1;
void *block = (size_t *)ptr - 1;

Наконец, замена malloc не удастся для любого типа, который требует большего выравнивания, чем size_t (хотя, вероятно, ваша система не имеет таких типов).

Другие вопросы по тегам