Why is there a "strdup" function, but not "memdup" function in the standard?
Asked Answered
S

7

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?
Submariner answered 1/12, 2012 at 20:49 Comment(9)
Wouldn't strdup just be a malloc and a memcpy?Cuirbouilli
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.Sulfonmethane
@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)Haigh
@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.Sulfonmethane
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.Submariner
@Submariner 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?Ciro
@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.Nobles
@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.Nobles
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.Azerbaijan
I
-7

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.

Incongruent answered 1/12, 2012 at 20:58 Comment(7)
there are memcpy(), memcmp(), memmem(), memchr(). it would make sense a void * memdup(const void * mem, size_t size) ?Allurement
@Allurement 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?Incongruent
as pointed before, the same way as memcpy() works. It's meant to duplicate a memory region that, by chance, is a data structure.Allurement
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.Incongruent
Except memdup would not be a duplicate of a structure. By name, it would duplicate an area of memory. It's memdup, not datastructuredup.Zennas
@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.Nobles
@AnT: If only I had a dollar for every time I saw this kind of attempt at StackOverflow...Gopherwood
B
19

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;
}
Behm answered 13/3, 2015 at 14:52 Comment(1)
This doesn't answer any of the 3 specific questionsJaniculum
D
8

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.

Dime answered 13/8, 2019 at 8:8 Comment(1)
This is the only response that actually answers any of the asked questions.Adaline
J
2

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.

Janiculum answered 4/8, 2023 at 14:49 Comment(0)
S
1

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;
}
Semidiurnal answered 16/1, 2018 at 12:41 Comment(1)
@Hooper Well, actually the NUL byte is copied from the NUL-terminated src string.Torr
B
1
  1. Is there some standard library function like this that I don't know about?

As of now, there isn't, but there are numerous libraries and even compiler extensions that provide their own portable implementation for memdup. Check out publib and Glib as well as a number of exogeneous allocators. The Gnulib also includes it as previously mentioned. These are a set of memory functions (memdup, memcpy, malloc, calloc, realloc, strdup, ...), prefixed with x. They are meant to also provide out-of-memory checking.

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

What is wrong with using memcpy / memmove and malloc ? Starting from C99, you can declare a Variable-Length Array as the buffer and use a loop to copy each byte individually:

uint8_t membuf[size]; /* Beware of Stack Overflows */
for(int i = 0; i < size; i++)
    membuf[i] = mem[i];

Though, a standard memcpy implementation might perform even better due to heavy optimizations (especially if the -O3 compilation flag has been set). Optimizations include: Loop unrolling, inlining and vectorization. All in all, I would say it is best if you just copy/paste this code and reuse it forever. Kind of how C is meant to be used in the first place.

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

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

    return out;
}
  1. C does not include strdup - it is not a standard C function. It is a POSIX function that just happens to be very common. Being so easy to implement, there are probably not enough reasons for memdup to be standardized. Moreover, there is a use-case ambiguity associated with this function. One should write their own memdup-like function with different implementation details depending on their specific requirements, such as memdup_hardcpy and memdup_deepcpy perhaps.
Blender answered 9/5 at 17:43 Comment(0)
C
-1

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.

Coattail answered 1/12, 2012 at 20:59 Comment(7)
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.Gala
@Gala memdup, like memcpy, could take a size parameter. I don't find this a compelling answer.Incongruent
@Gala 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.Kimberleykimberli
strlen+malloc+memcpy is likely to be more efficient.Azerbaijan
@TobySpeight Why exactly do you suppose so? A sane implementation would either just do those things, or else something system-specific that was tested to be more efficient. If you're concerned about the overhead of calling strdup in itself, don't be; compilers have understood basic inlining for a long time now.Benefield
@Karl, memcpy() is generally more efficient than strcpy() because it can copy large blocks at a time in a way that strcpy() can't due to the need to inspect each character and not attempt to read anything after the terminating null (which might not be legally accessible). Since we needed to obtain the length to allocate the right amount of memory, it's trivial to remember it and call memcpy() rather than strcpy().Azerbaijan
Sure, but unless you are tracking the length of the string separately, you still have to pay for the strlen call, which still has to inspect each byte.Benefield
I
-7

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.

Incongruent answered 1/12, 2012 at 20:58 Comment(7)
there are memcpy(), memcmp(), memmem(), memchr(). it would make sense a void * memdup(const void * mem, size_t size) ?Allurement
@Allurement 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?Incongruent
as pointed before, the same way as memcpy() works. It's meant to duplicate a memory region that, by chance, is a data structure.Allurement
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.Incongruent
Except memdup would not be a duplicate of a structure. By name, it would duplicate an area of memory. It's memdup, not datastructuredup.Zennas
@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.Nobles
@AnT: If only I had a dollar for every time I saw this kind of attempt at StackOverflow...Gopherwood

© 2022 - 2024 — McMap. All rights reserved.