What is the purpose of the strdup()
function in C?
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 current (C17) 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:
It tries to allocate enough memory to hold the old string (plus a '\0' character to mark the end of the string).
If the allocation failed, it sets
errno
toENOMEM
and returnsNULL
immediately. Setting oferrno
toENOMEM
is somethingmalloc
does in POSIX so we don't need to explicitly do it in ourstrdup
. If you're not POSIX compliant, ISO C doesn't actually mandate the existence ofENOMEM
so I haven't included that here(b).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.
One other thing to keep in mind, it looks like this is currently slated to be in the C2x iteration of the standard, along with strndup
, as per draft N2912
of the document.
(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
, orwcs
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
}
strcpy
, what's the point of strdup
? Safer for string copy? –
Wonderland strdup
is for those situations where you want heap memory allocated for the string copy. Otherwise you have to do it yourself. If you already have a big enough buffer (malloc'ed or otherwise), yes, use strcpy
. –
Jequirity errno
to ENOMEM
" is a POSIX spec - not a C one. If code needs to create strdup()
, likely not on a POSIX system, might not malloc()
also not set errno
? So to provide POSIX like functionality, perhaps this strdup()
should also set errno
as needed. Otherwise calling code should not count on errno
to ENOMEM
on failure via this strdup()
–
Markland { EDOM, EILSEQ, ERANGE }
as required error codes. Have updated the answer to account for this. –
Jequirity memcpy
instead as the "canonical strdup implementation" ;) –
Karame memcpy
variant would be canonical. It's possible it may be faster but I prefer to optimise for readability first :-) –
Jequirity strdup
and its sibling strndup
have been submitted for inclusion in the upcoming ISO C23 standard. –
Dhruv char * strdup(const char * s)
{
size_t len = 1+strlen(s);
char *p = malloc(len);
return p ? memcpy(p, s, len) : (errno = ENOMEM, 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()
).
EDIT: according to some documents, strdup()
sets errno
to ENOMEM
when allocation fails.
return memcpy(malloc(len), s, len);
as I prefer the crash on allocation rather than the NULL
on allocation failure. –
Wiggins NULL
doesn't have to crash; it's undefined. If you want to be sure it crashes, write an emalloc
which calls abort
upon fail. –
Goulette emalloc
even if it's not necessary on Solaris or Linux so that you'll be using it in the future when you write code on other platforms. –
Tirza 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.
strdup()
portable? No, not available in non-POSIX environment (trivially implementable anyway). But to say a POSIX function can do anything is quite pedantic. POSIX is another standard that's as good as C's and even more popular. –
Antonina strdup
function as an extension. On such an implementation, there's no guarantee that that strdup
behaves the same way as the POSIX function. I don't know of any such implementations, but a legitimate non-malicious implementation might provide char *strdup(char *)
for historic reasons, and reject attempts to pass in a const char *
. –
Revivalism 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.
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.
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.
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.
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,
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.)
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.
strdup
does not need to be a string constant, it must be a C string, ie a null terminated array of char
. –
Stratocumulus Using strdup you can get a modifiable copy of the string word or any string. In this way, you can change its contents without encountering the problems of replacing the hard memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const char* original = "Hello, World!";
char *copy = strdup(original); // Create a copy
if (copy != NULL) {
// Modify the copy
strcpy(copy, " Again Hello World \n");
printf("Original: %s\n", original);
printf("Copy: %s\n", copy);
free(copy);
} else {
printf("Memory allocation failed.\n");
}
return 0;
}
© 2022 - 2024 — McMap. All rights reserved.
strdupa
is dangerous and should not be used unless you've already determined thatstrlen
is very small. But then you could just use a fixed-size array on the stack. – Chordatestrdup
/strdupa
mean in Polish? – Windrow