Функция "memdup" в C?
В C вы можете использовать strdup
, чтобы кратко выделить буфер и скопировать в него строку. Однако, насколько мне известно, подобной функции для общей памяти не существует. Например, я не могу сказать
struct myStruct *foo = malloc(sizeof(struct myStruct));
fill_myStruct(foo);
struct myStruct *bar = memdup(foo, sizeof(struct myStruct));
// bar is now a reference to a new, appropriately sized block of memory,
// the contents of which are the same as the contents of foo
Поэтому мой вопрос трижды:
- Есть ли какая-то стандартная библиотечная функция, о которой я не знаю?
- Если нет, существует ли сжатый и предпочтительно стандартный способ сделать это без явных вызовов
malloc
и memcpy
?
- Почему C включает
strdup
, но не memdup
?
Ответы
Ответ 1
Создание копии произвольной структуры памяти не так прямо, как копирование строки. Как вы должны обрабатывать случай, когда структура содержит указатели на другие структуры (например, строки), например? Что значит "дублировать" такую структуру? На этот вопрос нет ни одного правильного ответа, в отличие от случая с строкой. В этом случае, вероятно, лучше просто позволить разработчику приложения создать механизм для создания копии структуры в соответствии с их вариантами использования, а не путать проблему, притворившись, что существует канонический способ ее обработки.
Ответ 2
Вы можете реализовать его с простой функцией:
void* memdup(const void* mem, size_t size) {
void* out = malloc(size);
if(out != NULL)
memcpy(out, mem, size);
return out;
}
Ответ 3
В GNU Gnulib есть void *xmemdup (void const *p, size_t s)
. xalloc.h
.
Обратите внимание, что он вызывает xalloc_die
в случае нехватки памяти.
Ответ 4
Вероятно, вы просто хотите определить memdup()
самостоятельно, а затем просто используйте его в своем коде, как уже было предложено. Моя версия функции следует.
void *
memdup(const void *src, size_t n)
{
void *dest;
dest = malloc(n);
if (dest == NULL)
return NULL;
return memcpy(dest, src, n);
}
Что касается обсуждения того, является ли memdup()
слишком тривиальным или даже избыточным, я так не думаю. Это так полезно для копирования структур в вашем коде. Стандарты ANSI/ISO и POSIX для стандартной библиотеки C содержат так много удобных функций, но, к сожалению, не этот.
Пример: повторная реализация strdup()
с помощью memdup()
.
char *
strdup(const char *src)
{
return memdup(src, strlen(src) + 1);
}
Пример: использование memdup()
для дублирования объекта.
int
some_function(const struct some_struct *some_const_data)
{
struct some_struct *my_mutable_copy;
if ((my_mutable_copy = memdup(some_const_data)) == NULL)
return -1;
...
return 0;
}
Ответ 5
Функция strdup считывает и копирует до нулевого значения в строке с нулевым завершением. Однако нормальные данные не имеют таких разделителей, поэтому вам нужно указать длину данных для копирования.