315
votes

What is the purpose of the strdup() function in C?

10
there is also strdupa() (in the GNU C library), a nice function that is similar to strdup(), but allocates memory on the stack. Your program don't need to free the memory explicitly as in case with strdup(), it will be freed automatically when you exit the function where strdupa() was calleddmityugov
strdupa is dangerous and should not be used unless you've already determined that strlen is very small. But then you could just use a fixed-size array on the stack.R.. GitHub STOP HELPING ICE
@slacker google translate isn't being helpful... What does strdup/strdupa mean in Polish?haneefmubarak
@haneefmubarak hereanatolyg
Here is the difference between strdup and strcpy stackoverflow.com/questions/14020380/strcpy-vs-strdupSiva Prakash

10 Answers

387
votes

Exactly what it sounds like, assuming you're used to the abbreviated way in which C and UNIX assigns words, it duplicates strings :-)

Keeping in mind it's actually not part of the ISO C standard itself(a) (it's a POSIX thing), it's effectively doing the same as the following code:

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

In other words:

  1. It tries to allocate enough memory to hold the old string (plus a '\0' character to mark the end of the string).

  2. If the allocation failed, it sets errno to ENOMEM and returns NULL immediately. Setting of errno to ENOMEM is something malloc does in POSIX so we don't need to explicitly do it in our strdup. If you're not POSIX compliant, ISO C doesn't actually mandate the existence of ENOMEM so I haven't included that here(b).

  3. Otherwise the allocation worked so we copy the old string to the new string(c) and return the new address (which the caller is responsible for freeing at some point).

Keep in mind that's the conceptual definition. Any library writer worth their salary may have provided heavily optimised code targeting the particular processor being used.


(a) However, functions starting with str and a lower case letter are reserved by the standard for future directions. From C11 7.1.3 Reserved identifiers:

Each header declares or defines all identifiers listed in its associated sub-clause, and *optionally declares or defines identifiers listed in its associated future library directions sub-clause.**

The future directions for string.h can be found in C11 7.31.13 String handling <string.h>:

Function names that begin with str, mem, or wcs and a lowercase letter may be added to the declarations in the <string.h> header.

So you should probably call it something else if you want to be safe.


(b) The change would basically be replacing if (d == NULL) return NULL; with:

if (d == NULL) {
    errno = ENOMEM;
    return NULL;
}

(c) Note that I use strcpy for that since that clearly shows the intent. In some implementations, it may be faster (since you already know the length) to use memcpy, as they may allow for transferring the data in larger chunks, or in parallel. Or it may not :-) Optimisation mantra #1: "measure, don't guess".

In any case, should you decide to go that route, you would do something like:

char *strdup(const char *src) {
    size_t len = strlen(src) + 1;       // String plus '\0'
    char *dst = malloc(len);            // Allocate space
    if (dst == NULL) return NULL;       // No memory
    memcpy (dst, src, len);             // Copy the block
    return dst;                         // Return the new string
}
88
votes
char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

Maybe the code is a bit faster than with strcpy() as the \0 char doesn't need to be searched again (It already was with strlen()).

52
votes

No point repeating the other answers, but please note that strdup() can do anything it wants from a C perspective, since it is not part of any C standard. It is however defined by POSIX.1-2001.

18
votes

From strdup man:

The strdup() function shall return a pointer to a new string, which is a duplicate of the string pointed to by s1. The returned pointer can be passed to free(). A null pointer is returned if the new string cannot be created.

4
votes

strdup() does dynamic memory allocation for the character array including the end character '\0' and returns the address of the heap memory:

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

So, what it does is give us another string identical to the string given by its argument, without requiring us to allocate memory. But we still need to free it, later.

3
votes

It makes a duplicate copy of the string passed in by running a malloc and strcpy of the string passed in. The malloc'ed buffer is returned to the caller, hence the need to run free on the return value.

3
votes

strdup and strndup are defined in POSIX compliant systems as:

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

The strdup() function allocates sufficient memory for a copy of the string str, does the copy, and returns a pointer to it.

The pointer may subsequently be used as an argument to the function free.

If insufficient memory is available, NULL is returned and errno is set to ENOMEM.

The strndup() function copies at most len characters from the string str always null terminating the copied string.

1
votes

The most valuable thing it does is give you another string identical to the first, without requiring you to allocate memory (location and size) yourself. But, as noted, you still need to free it (but which doesn't require a quantity calculation, either.)

1
votes

The statement:

strcpy(ptr2, ptr1);

is equivalent to (other than the fact this changes the pointers):

while(*ptr2++ = *ptr1++);

Whereas:

ptr2 = strdup(ptr1);

is equivalent to:

ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);

So, if you want the string which you have copied to be used in another function (as it is created in heap section), you can use strdup, else strcpy is enough,

0
votes

The strdup() function is a shorthand for string duplicate, it takes in a parameter as a string constant or a string literal and allocates just enough space for the string and writes the corresponding characters in the space allocated and finally returns the address of the allocated space to the calling routine.