strdup(3)
C library function
Allocates a copy of a string with malloc and returns its address, or NULL. Part of standard C since C23; the copy must be released with free.
#include <string.h>
char *strdup(const char *s);Description
strdup creates a copy of the string s in a block allocated as if by malloc(3), and returns the address of that block. It does in one call what would otherwise take three lines: measure with strlen(3), allocate strlen(s) + 1 bytes, copy with strcpy(3). The copy is independent of the original: changing one does not touch the other, and the copy outlives the function that created it.
For a long time, strdup existed only in POSIX, not in standard C. C23 added it to <string.h>, along with its cousin strndup, which copies at most n characters.
Return value
The address of the copy, which you hand back with free(3) once you no longer need it. If the allocation fails, strdup returns NULL and errno gives the error, as with malloc.
Pitfalls
Every strdup is a hidden malloc. A copy that is never freed is a leak, which Valgrind classifies as “definitely lost” with the call stack malloc, strdup, then the line of your code that called strdup.
Test the return value before using the copy: on NULL, the first access is undefined behavior.
strdup(NULL) is undefined behavior too, since s must point to a string.
In strict mode, glibc only declares strdup if the requested standard includes it, or if a POSIX macro asks for it. With -std=c17 and no POSIX macro, the header does not declare it, and GCC 14 and later turn that into an error. With -std=c23, or with the default mode of GCC 15 (gnu23), it is available. If you have to build as strict C17, add #define _POSIX_C_SOURCE 200809L before the #include lines.
Example
#include <stdio.h>#include <stdlib.h>#include <string.h>
int main(void){ char buffer[32] = "draft"; char *copy = strdup(buffer);
if (copy == NULL) return 1; strcpy(buffer, "overwritten"); printf("buffer = %s, copy = %s\n", buffer, copy); free(copy); return 0;}$ gcc -Wall -Wextra -g duplicate.c -o duplicate$ ./duplicatebuffer = overwritten, copy = draft$ valgrind -q ./duplicatebuffer = overwritten, copy = draft$ gcc -std=c17 -Wall -Wextra duplicate.c -o duplicate17duplicate.c: In function 'main':duplicate.c:8:18: error: implicit declaration of function 'strdup'; did you mean 'strcmp'? [-Wimplicit-function-declaration] 8 | char *copy = strdup(buffer); | ^~~~~~ | strcmpduplicate.c:8:18: error: initialization of 'char *' from 'int' makes pointer from integer without a cast [-Wint-conversion]$ gcc -std=c23 -Wall -Wextra duplicate.c -o duplicate23$ ./duplicate23buffer = overwritten, copy = draftOverwriting buffer does not change copy, which lives in its own block on the heap. Valgrind in -q mode says nothing: the block was freed. In strict C17, the function is not declared and the build fails; in C23, it compiles without a single change to the code.
strdup
Write gm_strdup, which allocates the string's length plus one byte with malloc, then copies the string into that block.