Восстановить значение, установленное 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? Этот текущий метод дает мне ошибки


person Community    schedule 26.09.2014    source источник
comment
Я не думаю, что ваш вызов memset() делает то, что вы думаете. Из того, что вы описали, вы вообще не хотите использовать memset().   -  person Greg Hewgill    schedule 26.09.2014
comment
В дополнение к неправильному использованию memset ваше вычисление retval в my_malloc также является полностью фиктивным.   -  person Employed Russian    schedule 26.09.2014


Ответы (1)


Вам действительно нужно прочитать документацию memset. Он устанавливает для блока памяти все байты одинаковыми. Эффект memset(block, sz, sizeof(size_t)) состоит в том, чтобы установить для первых 8 (или любого другого размера size_t) байтов 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 (хотя вполне вероятно, что в вашей системе нет таких типов).

person M.M    schedule 26.09.2014