Question

C strdup(): Duplicating Strings with Dynamic Memory

cfunctionstrdup

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:

  1. Finds the length of the source string, excluding its terminating \0 character.
  2. Allocates enough heap memory for all characters plus one for \0.
  3. Copies the source string into that memory.
  4. 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.
Take Quiz

Syntax and Examples

The basic syntax is:

char *strdup(const char *source);
  • source is a valid null-terminated string.
  • The result is a newly allocated duplicate, or NULL when 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:

  1. label points to the string literal "draft".
  2. strdup(label) measures the source string. Its length is 5.
  3. It allocates 6 bytes: five letters and one terminating \0.
  4. It copies d, r, a, f, t, and \0 into the new allocation.
  5. saved_label receives the pointer to that allocation.
  6. The NULL check ensures the program does not use memory if allocation failed.
  7. saved_label[0] = 'D' changes only the duplicate, producing "Draft".
  8. The output is:
draft / Draft
  1. free(saved_label) releases the dynamically allocated copy. Do not use saved_label after 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);
Take Quiz

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

ApproachCreates separate character storage?Can modify result?Must call free()?
char *b = a;NoDepends on what a points toNo new allocation
strdup(a)YesYes, if successfulYes
char buffer[50]; strcpy(buffer, a);YesYesNo, but buffer has fixed capacity
malloc(strlen(a) + 1) then copyYesYesYes

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.

Take Quiz

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 NULL as the source.
  • Do not use the result after free().
  • strdup() is POSIX, not ISO C.
  • The duplicate includes the terminating \0 character.
  • 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.

Take Quiz

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.

Take Quiz

Keep learning

Related questions

View more