15

In C, you can use strdup to succinctly allocate a buffer and copy a string into it. As far as I'm aware, however, there is no similar function for general memory. For example, I can't say

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

My question, then, is threefold:

  1. Is there some standard library function like this that I don't know about?
  2. If not, is there a succinct and preferably standard way to do this without explicit calls to malloc and memcpy?
  3. Why does C include strdup but not memdup?
imreal
  • 10,178
  • 2
  • 32
  • 48
Dan
  • 2,952
  • 4
  • 23
  • 29
  • 2
    Wouldn't `strdup` just be a `malloc` and a `memcpy`? – Marlon Dec 01 '12 at 20:52
  • 3
    It's two function calls. (`malloc()` and `memcpy()`) Seems a bit too trivial to be worth making a function for. `strdup()` is a bit more complicated if you want to avoid too many passes over the string. – Mysticial Dec 01 '12 at 20:52
  • 3
    @Mystical: What implementation of `strdup()` have you seen that doesn't require exactly 2 passes over the input string? (once to size the buffer, once to copy) – Billy ONeal Dec 01 '12 at 20:57
  • @BillyONeal Now that I think about it, it's still only 3 function calls. But a speculative implementation could possibly go below 2 passes on average - at the cost of overallocating. – Mysticial Dec 01 '12 at 20:58
  • 2
    My purpose is mostly for code readability - I'd like to go from `struct myStruct *bar = (struct myStruct *)malloc(sizeof(struct myStruct)); memcpy(bar, foo, sizeof(struct myStruct));` to just a single, relatively short line where it's obvious what's going on. – Dan Dec 01 '12 at 21:00
  • 4
    @Dan Don't cast the result of `malloc`. Aside from that, C doesn't include `strdup`. POSIX does, though, so it's widespread. But you can't rely on it being available. And `struct myStruct *bar = malloc(sizeof *bar); *bar = *foo;` doesn't look too bad, does it? – Daniel Fischer Dec 01 '12 at 21:09
  • @Dan: *"Why does C include strdup but not memdup?"*. There is no `strdup` in C. It is not a standard function. It is provided by your implementation on its own accord. If your implementation decided to proivide `strdup`, there's a chance it provides `memdup` as well. If it does not, you can always implement it yourself. – AnT stands with Russia Oct 16 '16 at 16:25
  • @Daniel Fischer: Firstly, it will look a lot worse if you attempt to use it with "struct hack" idiom. Secondly, even when it is short, it still a sufficiently "atomic" functionality to deserve a dedicated function. – AnT stands with Russia Oct 16 '16 at 16:29
  • 1
    Note that if you implement such a function (as recommended in some answers), you __*must not* call it `memdup()`__ - all names beginning with `mem` are reserved for future use by the Standard Library. – Toby Speight Aug 13 '19 at 08:16

6 Answers6

20

You can implement it whith a simple function:

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

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

   return out;
}
Braden Best
  • 8,830
  • 3
  • 31
  • 43
Kabloc
  • 309
  • 2
  • 6
6

There is void *xmemdup (void const *p, size_t s) in GNU Gnulib's xalloc.h.

Note that it calls xalloc_die in case of insufficient memory.

Marc
  • 4,327
  • 4
  • 30
  • 46
0

You probably just want to define memdup() yourself and then simply use it in your code as already suggested. My version of the function follows.

void *memdup(const void *src, size_t n)
{
    void *dest;

    dest = malloc(n);
    if (dest == NULL)
            return NULL;

    return memcpy(dest, src, n);
}

As for the discussion whether memdup() is too trivial or even redundant, I don't think so. It is so useful for copying structures in your code. Both ANSI/ISO and POSIX standards for the C standard library contain so many convenience functions but unfortunately not this one.

Example: Reimplementation of strdup() using memdup().

char *strdup(const char *src)
{
    return memdup(src, strlen(src) + 1);
}

Example: Using memdup() to duplicate an object.

int some_function(const struct some_struct *some_const_data)
{
    struct some_struct *my_mutable_copy;

    my_mutable_copy = memdup(some_const_data, sizeof *some_const_data);
    if (my_mutable_copy == NULL)
        return -1;

    ...

    return 0;
}
Pavel Šimerda
  • 5,783
  • 1
  • 31
  • 31
0

Why does C include strdup but not memdup?

Prior to C23, strdup was not a C standard library function. It was a POSIX function though. And you can notice the pattern that prior to the dynamic memory TR, aside from the functions that exist to allocate memory, nothing returns you a pointer to a dynamically allocated memory buffer that you can call free on later (getdelim, getline, strdup, strndup - none of these were standard functions). I don't know the reasoning behind this design choice, but I guess memdup was also not implemented for the same reason.

Is there some standard library function like this that I don't know about?

No.

If not, is there a succinct and preferably standard way to do this without explicit calls to malloc and memcpy?

No.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
-2

The strdup function reads and copies up to the null on a null terminated string. However, normal data doesn't have any such delimiters, and therefore you need to give it the length of the data to copy.

Jimadilo
  • 497
  • 3
  • 10
  • 2
    This is the correct answer. The reason why strdup exists is not just to wrap two calls into one, but because of the logic to scan for the null byte, since doing a malloc+strcpy would cause a redundant strlen. This is not needed for memdup, which is why it isn't particularly justified when a simple malloc + memcpy would suffice. – rdb Dec 04 '14 at 18:17
  • 7
    @rdb memdup, like memcpy, could take a size parameter. I don't find this a compelling answer. – tvanfosson Dec 18 '14 at 13:58
  • 2
    @rdb Yes, `strdup` wraps instead three calls into one, a `strlen` call is certainly not redundant - you need to determine the length of the string (or the amount of memory needed) somehow. Normally you would need to allocate memory before copying the string and in that case you would need to basically call `strlen`, `malloc` and `strcpy` in that order. – skyking Apr 19 '17 at 13:24
  • `strlen`+`malloc`+`memcpy` is likely to be more efficient. – Toby Speight Aug 13 '19 at 08:18
-6

Making a copy of an arbitrary memory structure isn't as straight forward as copying a string. How should you handle the case where the structure contains pointers to other structures (such as strings) for example? What does it mean to "duplicate" such a structure? There isn't one right answer to this, unlike the case for string. In that case, it's probably better to just let the application developer create a mechanism for making a copy of the structure according to their use cases rather than confuse the issue by pretending that there is a canonical way to handle it.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 12
    there are memcpy(), memcmp(), memmem(), memchr(). it would make sense a `void * memdup(const void * mem, size_t size)` ? – user666412 Oct 29 '14 at 13:26
  • @user666412 how exactly would memdup work if the structure contained pointers? Does it do a shallow copy (retain the pointers) or a deep copy (recursively duplicate the related objects)? In C, how does it even know there are even pointers inside the structure? – tvanfosson Oct 29 '14 at 13:58
  • 7
    as pointed before, the same way as memcpy() works. It's meant to duplicate a memory region that, by chance, is a data structure. – user666412 Oct 29 '14 at 17:18
  • I disagree with the sentiment that "duplicate" is the same as "copy" in the shallow sense you use. A duplicate string is, in fact, a copy of the original string in a new location. A duplicate data structure, to my mind, would need to be a deep copy of the structure to maintain the "duplicate" semantics. While I can't delve into the minds of the original developers, to me the possible confusion is a strong argument for not supplying the method. – tvanfosson Dec 18 '14 at 13:57
  • 11
    Except memdup would not be a duplicate of a structure. By name, it would duplicate an area of memory. It's memdup, not datastructuredup. – Taywee Dec 12 '15 at 00:08
  • 8
    @Tim Ring: ... and same issue applies to the plain assignment. The fact that low level `memdup` cannot properly copy a structure cannot be meaningfully used as an argument against `memdup`. This answer is just a demagogic attempt to fill the issue with unnecessary noise. – AnT stands with Russia Oct 16 '16 at 16:31
  • 3
    @AnT: If only I had a dollar for every time I saw this kind of attempt at StackOverflow... – user541686 Jan 16 '18 at 12:49