Восстановить значение, установленное 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
(хотя, вероятно, ваша система не имеет таких типов).