Использование memcpy для копирования структуры в кучу

Я пытаюсь поместить структуру с именем «Держатель» в кучу, используя следующий код, но получаю ошибку сегментации, когда пытаюсь использовать memcpy:

Holder hold;
Holder *heapHold = memcpy(heapHold, &hold, sizeof(Holder));

Почему я ошибаюсь?


person hut123    schedule 22.04.2011    source источник


Ответы (3)


Holder hold;

Это объявляет hold как переменную типа Holder. hold не инициализирован.

Holder *heapHold = memcpy(heapHold, &hold, sizeof(Holder));

memcpy(dest, source, size) копирует size байт из source в dest. Предполагается, что dest выделено правильно. Поскольку вы не выделяете для него память, вы получаете segfault.

Вам нужно выделить память:

Holder *heapHold = malloc(sizeof *heapHold);
if (heapHold == NULL) {
    /* failed to allocate, handle error here */
} else {
    /* OK to copy.  Make sure you initialize 'hold' to something valid */
    memcpy(heapHold, &hold, sizeof *heapHold);
}

Кроме того, memcpy() возвращает первый параметр. Присвоение возвращаемого значения heapHold аналогично произнесению a = a;, т. е. ничего не делает. В большинстве практических случаев возвращаемое значение memcpy() игнорируется.

person Alok Singhal    schedule 22.04.2011
comment
Это по-прежнему предполагает, что допустимо копировать экземпляры Holder с memcpy в первую очередь. Конечно, в C это обычно так... - person Karl Knechtel; 22.04.2011
comment
@Карл, можешь привести пример экземпляра, где &holder нельзя скопировать? - person Alok Singhal; 22.04.2011
comment
Структуры, которые содержат указатели на себя (внутри) или содержат указатели на данные, которые должны быть глубоко скопированы. - person Karl Knechtel; 27.04.2011

Сначала вам нужно выделить память для heapHold. В настоящее время memcpy записывает на какой-то случайный адрес (heapHold не инициализирован), что приводит к сбою.

Holder hold;
Holder *heapHold = malloc(sizeof(Holder));
memcpy(heapHold, &hold, sizeof(Holder));
person nobody    schedule 22.04.2011

Holder hold;
Holder *heapHold = malloc(sizeof(Holder));
memcpy(heapHold,&hold,sizeof(Holder));

Переменная heapHold в memcpy(heapHold, &hold, sizeof(Holder)); по-прежнему не инициализирована (и ни один буфер не был выделен), поэтому она указывает на недопустимую память.

Кстати (я всегда забываю об этом) - когда вы выделяете память с помощью malloc, не делайте forget, чтобы освободить ее позже.

person MByD    schedule 22.04.2011