функция "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

мой вопрос, тогда, состоит из трех частей:

  1. есть ли какая-то стандартная библиотечная функция, о которой я не знаю?
  2. если нет, есть ли краткий и предпочтительно стандартный способ сделать это без явных вызовов malloc и memcpy?
  3. почему C включает strdup а не memdup?

4 ответов


создание копии произвольной структуры памяти не так прямо, как копирование строки. Как следует обрабатывать случай, когда структура содержит указатели на другие структуры (например, строки)? Что значит "дублировать" такую структуру? На это нет ни одного правильного ответа, в отличие от случая для string. В этом случае, вероятно, лучше просто позволить разработчику приложения создать механизм для создания копии структуры в соответствии с их использованием случаи, а не путать вопрос, делая вид, что есть канонический способ справиться с ним.


вы можете реализовать его с помощью простой функции:

void* memdup(const void* mem, size_t size) { 
   void* out = malloc(size);

   if(out != NULL)
       memcpy(out, mem, size);

   return out;
}

вы, вероятно, просто хотите определить 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;
}

функция strdup считывает и копирует до null в строке с нулевым завершением. Однако обычные данные не имеют таких разделителей, и поэтому вам нужно дать ему длину данных для копирования.