Question
What is the purpose of the strdup() function in C, and how should its returned string be managed?
Short Answer
strdup() creates an independent, dynamically allocated copy of a null-terminated C string. You will learn how it works, why free() is required, and how to handle errors safely.
Concept
strdup() means string duplicate. It accepts a pointer to a null-terminated character string and returns a pointer to a newly allocated copy of that string.
char *copy = strdup("hello");
After this call, copy points to memory containing its own characters: "hello\0". It is separate from the original string, so modifying the copy does not modify the original.
Conceptually, strdup() performs these steps:
- Finds the length of the source string, excluding its terminating
\0character. - Allocates enough heap memory for all characters plus one for
\0. - Copies the source string into that memory.
- Returns the address of the new memory.
The allocated memory belongs to the caller. When it is no longer needed, release it with free().
char *name = strdup("Ada");
if (name != NULL) {
printf("%s\n", name);
free(name);
}
strdup() is specified by POSIX, not by the ISO C standard. It is widely available on Unix-like systems. In strictly portable ISO C programs, write an equivalent helper using malloc() and memcpy() or strcpy().
Mental Model
Think of a string as text written on a sheet of paper.
- A pointer to a string is like being given the address of the original sheet.
strdup()is like photocopying that sheet and giving you the new copy.- You may write on your copy without changing the original.
- Because the photocopy uses new storage, you are responsible for throwing it away later with
free().
Simply assigning a pointer does not make a copy:
char *a = "hello";
char *b = a; // Both pointers refer to the same string.
Using strdup() does:
char *a = "hello";
char *b = strdup(a); // b refers to separately allocated memory.
Syntax and Examples
The basic syntax is:
char *strdup(const char *source);
sourceis a valid null-terminated string.- The result is a newly allocated duplicate, or
NULLwhen allocation fails. - The caller must eventually call
free()on a successful result.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *original = "coffee";
char *copy = strdup(original);
if (copy == NULL) {
fprintf(stderr, "Could not allocate memory\n");
return 1;
}
copy[0] = 'C';
printf("original: %s\n", original);
printf("copy: %s\n", copy);
free(copy);
return 0;
}
Output:
original: coffee
copy: Coffee
original points to a string literal and must not be modified. copy points to writable heap memory, so changing its first character is valid.
On systems where the declaration is available, include:
#include <string.h>
When compiling with strict language modes, you may need to enable POSIX declarations, for example:
#define _POSIX_C_SOURCE 200809L
#include <string.h>
Define the feature-test macro before including system headers.
Step by Step Execution
Consider this program fragment:
const char *label = "draft";
char *saved_label = strdup(label);
if (saved_label == NULL) {
return 1;
}
saved_label[0] = 'D';
printf("%s / %s\n", label, saved_label);
free(saved_label);
Step by step:
labelpoints to the string literal"draft".strdup(label)measures the source string. Its length is 5.- It allocates 6 bytes: five letters and one terminating
\0. - It copies
d,r,a,f,t, and\0into the new allocation. saved_labelreceives the pointer to that allocation.- The
NULLcheck ensures the program does not use memory if allocation failed. saved_label[0] = 'D'changes only the duplicate, producing"Draft".- The output is:
draft / Draft
free(saved_label)releases the dynamically allocated copy. Do not usesaved_labelafter this point unless you assign it a new valid value.
Real World Use Cases
strdup() is useful whenever a program must keep its own copy of text instead of borrowing someone else's pointer.
- Configuration parsing: Copy a value such as
"production"from a temporary input buffer before the buffer is reused. - Command-line tools: Save command-line arguments in a data structure that outlives the parsing step.
- HTTP or API processing: Duplicate a request header or JSON-derived text before destroying the request buffer.
- Data structures: Store independently owned names in a linked list, hash table, or record.
- Environment data: Copy a value returned by
getenv()if it must remain stable after environment-related operations. - Text transformations: Duplicate input text before editing it in place with functions such as
strtok()or direct character changes.
For example, a contact record can own its name:
struct Contact {
char *name;
};
struct Contact contact = {0};
contact.name = strdup("Lin");
/* Use contact.name... */
free(contact.name);
Real Codebase Usage
In real projects, strdup() is usually paired with clear ownership rules: the code that duplicates a string owns the result and must free it, or it transfers that responsibility to another object.
Validate allocation immediately
char *path_copy = strdup(path);
if (path_copy == NULL) {
return -1;
}
This is a guard clause. It prevents a later null-pointer dereference.
Clean up on later failure
char *host_copy = strdup(host);
if (host_copy == NULL) {
return -1;
}
char *port_copy = strdup(port);
if (port_copy == NULL) {
free(host_copy);
return -1;
}
/* Use both copies. */
free(port_copy);
free(host_copy);
Transfer ownership into a structure
struct User {
char *username;
};
int user_set_name(struct User *user, const char *name) {
char *new_name = strdup(name);
if (new_name == NULL) {
return -1;
}
free(user->username);
user->username = new_name;
return 0;
}
The function makes a new copy before freeing the old value. If allocation fails, the existing username remains intact.
Provide a matching destructor
When a structure owns duplicated strings, create a cleanup function:
void user_destroy(struct User *user) {
free(user->username);
user->username = NULL;
}
Common Mistakes
Forgetting to free the result
This leaks memory when repeated:
char *copy = strdup(input);
/* copy is never freed */
Fix it by freeing the pointer after its final use:
free(copy);
Ignoring allocation failure
strdup() can return NULL if memory cannot be allocated.
char *copy = strdup(input);
printf("%s\n", copy); // Unsafe if copy is NULL.
Check first:
char *copy = strdup(input);
if (copy == NULL) {
return 1;
}
Modifying a string literal instead of the duplicate
This has undefined behavior:
char *text = "hello";
text[0] = 'H';
Make a writable copy:
char *text = strdup("hello");
if (text != NULL) {
text[0] = 'H';
free(text);
}
Using the pointer after free()
This is undefined behavior:
free(copy);
printf("%s\n", copy);
After freeing, do not read or write through the pointer. Setting it to NULL can make accidental reuse easier to detect:
free(copy);
copy = NULL;
Freeing memory that was not dynamically allocated
Only free the pointer returned by strdup() (or another allocation function), not the original string unless it too is owned allocated memory.
const char *original = "hello";
char *copy = strdup(original);
free(copy); // Correct.
/* free(original); */ // Incorrect: original is a string literal.
Passing NULL as the source
strdup(NULL) has undefined behavior. Check optional inputs before duplicating them.
Comparisons
| Approach | Creates separate character storage? | Can modify result? | Must call free()? |
|---|---|---|---|
char *b = a; | No | Depends on what a points to | No new allocation |
strdup(a) | Yes | Yes, if successful | Yes |
char buffer[50]; strcpy(buffer, a); | Yes | Yes | No, but buffer has fixed capacity |
malloc(strlen(a) + 1) then copy | Yes | Yes | Yes |
Pointer assignment versus duplication
char text[] = "cat";
char *same = text;
same[0] = 'C';
printf("%s\n", text); // Cat
same and text refer to the same character array. Assignment copies an address, not the characters.
strdup() versus manual allocation
A portable ISO C equivalent is:
#include <stdlib.h>
#include <string.h>
char *duplicate_string(const char *source) {
size_t size = strlen(source) + 1;
char *copy = malloc(size);
if (copy != NULL) {
memcpy(copy, source, size);
}
return copy;
}
This is essentially what strdup() provides. The manual version is useful when POSIX is unavailable or when you need custom allocation behavior.
Cheat Sheet
#include <stdlib.h>
#include <string.h>
char *copy = strdup(source);
if (copy == NULL) {
/* Handle allocation failure. */
}
/* Use or modify copy. */
free(copy);
strdup()duplicates a null-terminated string.- Return type:
char *. - Success: pointer to newly allocated writable memory.
- Failure:
NULL. - Allocation: heap memory.
- Cleanup: call
free()exactly once for each successful duplication. - Do not pass
NULLas the source. - Do not use the result after
free(). strdup()is POSIX, not ISO C.- The duplicate includes the terminating
\0character. - Pointer assignment copies only the pointer;
strdup()copies the characters.
FAQ
What does strdup() return in C?
It returns a pointer to a newly allocated copy of the source string. If allocation fails, it returns NULL.
Does strdup() allocate memory?
Yes. It allocates heap memory large enough for the characters in the source string and its terminating null character.
Do I need to free a string returned by strdup()?
Yes. Call free() once when the duplicate is no longer needed.
Is strdup() part of standard C?
No. It is part of POSIX and is commonly available on Unix-like systems. Strictly portable C code can implement the same behavior with malloc() and a copy operation.
Can I modify the result of strdup()?
Yes, if it did not return NULL. The returned allocation is writable.
Does changing a strdup() result change the original string?
No. The duplicate has separate storage, so changes affect only the copy.
What happens if I call strdup(NULL)?
The behavior is undefined. Ensure the source pointer refers to a valid null-terminated string first.
Why might the compiler say strdup() is implicitly declared?
The appropriate POSIX declaration may not be enabled in the selected compilation mode. Include <string.h> and, where needed, define a suitable POSIX feature-test macro before including headers.
Mini Project
Description
Create a small program that stores a user-entered label safely. The input buffer can be reused or changed, but the saved label must remain an independent copy. This demonstrates why programs duplicate strings before keeping them in longer-lived data structures.
Goal
Read one label, duplicate it with strdup(), convert the saved copy to uppercase, print it, and release its memory.
Requirements
Read a label of up to 99 characters using fgets().
Remove the trailing newline if one was read.
Use strdup() to create a dynamically allocated copy of the label.
Check whether duplication succeeded before using the copy.
Convert only the duplicate to uppercase and print it.
Free the duplicated string before the program exits.
Keep learning
Related questions
2D Array Loop Order and Cache Performance in C
Learn why swapping nested loops changes 2D array performance in C, using row-major memory layout, cache locality, and practical benchmarks.
Array-to-Pointer Conversion in C and C++ Explained
Learn what array-to-pointer conversion means in C and C++, how array decay works, and how it differs from a pointer to an array.
Building More Fault-Tolerant Embedded C++ Applications for Radiation-Prone ARM Systems
Learn practical C++ and compile-time techniques to reduce soft-error damage in embedded ARM systems exposed to radiation.