Skip to content

Understanding Dangling Pointers in C

This article is intended for intermediate and advanced C programmers. It assumes familiarity with pointers and dynamic memory allocation and explores common dangling pointer scenarios encountered in real-world applications.


What Is a Dangling Pointer?

A dangling pointer is a pointer that refers to a memory location that is no longer valid. Although the pointer still contains an address, the object it once pointed to no longer exists.

Unlike a memory leak, where the allocated memory still exists but the pointer to it is lost, a dangling pointer represents the opposite situation: the pointer still exists, but the memory it points to is no longer valid.

Dereferencing a dangling pointer results in undefined behavior. Depending on the program and the system, it may appear to work correctly, produce incorrect results, corrupt data, or cause the program to crash.


Scenario 1: Accessing Memory After free()

The most common way to create a dangling pointer is by freeing dynamically allocated memory while continuing to use the pointer.

When free() is called, the allocated memory is returned to the heap and is no longer owned by the program. However, the pointer itself is not modified. It continues to store the same memory address, even though that address no longer refers to valid memory.

As a result, the pointer becomes a dangling pointer. Any attempt to read from or write to the memory through that pointer results in undefined behavior.

Example

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int *ptr = malloc(sizeof(int));

    if (ptr == NULL)
    {
        return 1;
    }

    *ptr = 100;

    free(ptr);

    printf("%d\n", *ptr);    /* Undefined behavior */

    return 0;
}

In this example, ptr initially points to a valid block of dynamically allocated memory. After calling free(ptr), the allocated memory is released, but ptr still contains the same address.

Dereferencing ptr after it has been freed is unsafe because the memory no longer belongs to the program. The program may appear to work correctly, produce incorrect results, or crash depending on how the memory is reused by the system.


Scenario 2: Multiple Pointers to the Same Memory

A dangling pointer can also occur when multiple pointers refer to the same dynamically allocated memory.

If one pointer releases the memory using free(), every other pointer that still refers to that memory immediately becomes a dangling pointer. Although these pointers still contain the original memory address, the memory they refer to is no longer valid.

Example

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int *ptr1 = malloc(sizeof(int));

    if (ptr1 == NULL)
    {
        return 1;
    }

    int *ptr2 = ptr1;    /* Both pointers refer to the same memory */

    *ptr1 = 100;

    free(ptr1);

    printf("%d\n", *ptr2);    /* Undefined behavior */

    return 0;
}

Initially, both ptr1 and ptr2 point to the same dynamically allocated memory. When free(ptr1) is called, that memory is released.

Although ptr2 still contains the original address, the memory is no longer valid. Therefore, ptr2 becomes a dangling pointer, and dereferencing it results in undefined behavior.

When multiple pointers refer to the same memory block, programmers must ensure that no pointer is used after the memory has been released.


Scenario 3: Returning the Address of a Local Variable

A dangling pointer can also occur when a function returns the address of a local (automatic) variable.

Local variables are stored on the stack and exist only while the function is executing. When the function returns, its stack frame is automatically removed, destroying all local variables. Any pointer that refers to those variables immediately becomes a dangling pointer.

Example

#include <stdio.h>

int *getValue(void)
{
    int value = 100;

    return &value;    /* Returns address of a local variable */
}

int main(void)
{
    int *ptr = getValue();

    printf("%d\n", *ptr);    /* Undefined behavior */

    return 0;
}

In this example, value exists only while getValue() is executing. When the function returns, the stack frame is destroyed and value no longer exists.

Although ptr still contains the address that once belonged to value, that address is no longer valid. Dereferencing ptr therefore results in undefined behavior.

For this reason, a function should never return the address of a local (automatic) variable.


Consequences of Dangling Pointers

Dangling pointers are particularly dangerous because they often appear to work correctly. The pointer still contains a memory address, and the program may even produce the expected output during testing. However, the memory is no longer valid, so any access through the pointer results in undefined behavior.

Depending on how the freed memory is reused by the operating system or runtime environment, dereferencing a dangling pointer may:

  • Read incorrect or unexpected data.
  • Modify memory belonging to another object.
  • Corrupt the program's internal data.
  • Cause the program to crash.
  • Introduce security vulnerabilities.

Because undefined behavior is unpredictable, the same program may work correctly on one system, fail on another, or even behave differently each time it is executed.

For this reason, dangling pointers are among the most difficult bugs to detect and debug in C programs.


Preventing Dangling Pointers

Although dangling pointers can lead to serious bugs, they can usually be avoided by following a few simple programming practices.

  • Do not use a pointer after calling free(). Once dynamically allocated memory has been released, the pointer should no longer be dereferenced.

  • Set pointers to NULL after calling free(). Assigning NULL does not prevent the memory from being released, but it prevents the pointer from referring to an invalid memory location. Attempting to dereference a NULL pointer is easier to detect than using a dangling pointer.

  • Never return the address of a local variable. Local variables exist only while a function is executing. Returning their addresses produces dangling pointers as soon as the function returns.

  • Be careful when multiple pointers refer to the same memory. Once one pointer releases the memory, every other pointer that refers to the same memory becomes dangling and must no longer be used.

  • Clearly define pointer ownership. When several parts of a program share pointers, it should always be clear which part is responsible for releasing the allocated memory.

By consistently following these practices, programmers can avoid dangling pointers and write safer, more reliable C programs.


Dangling Pointer vs. NULL Pointer

A NULL pointer and a dangling pointer are fundamentally different concepts, although they are often confused.

A NULL pointer intentionally points to no valid memory location. It is safe to compare against NULL and assign to a pointer, but it must not be dereferenced.

int *ptr = NULL;

A dangling pointer, on the other hand, points to a memory location that was once valid but is no longer valid. This commonly occurs after dynamically allocated memory has been released using free().

int *ptr = malloc(sizeof(int));

free(ptr);      /* ptr is now a dangling pointer */

A dangling pointer can be converted into a NULL pointer by explicitly assigning NULL after the memory has been freed.

free(ptr);
ptr = NULL;

The following table summarizes the differences.

NULL Pointer Dangling Pointer
Points to no valid memory location. Points to memory that is no longer valid.
Intentionally initialized to NULL. Typically created after free() or by returning the address of a local variable.
Safe to compare with NULL. Appears valid but references invalid memory.
Must not be dereferenced. Must not be dereferenced.
Can be safely passed to free(). Passing a dangling pointer to free() again results in undefined behavior.

Although neither type of pointer should ever be dereferenced, a NULL pointer is generally safer because it explicitly indicates that no valid object is being referenced. A dangling pointer, however, still contains an address, making it much easier to accidentally access invalid memory.


Summary

A dangling pointer is a pointer that refers to a memory location that is no longer valid. Although the pointer still contains an address, the object it once pointed to no longer exists.

Dangling pointers commonly occur when:

  • Dynamically allocated memory is accessed after calling free().
  • Multiple pointers refer to the same memory and one of them releases it.
  • A function returns the address of a local (automatic) variable.

Because dereferencing a dangling pointer results in undefined behavior, the program may produce incorrect results, corrupt memory, crash unexpectedly, or appear to work correctly while hiding subtle bugs.

Dangling pointers can be avoided by never using pointers after calling free(), setting pointers to NULL after releasing memory, avoiding the return of addresses of local variables, and carefully managing pointers that share the same memory.

By understanding how dangling pointers arise and following safe programming practices, programmers can write more robust, reliable, and secure C programs.


C/C++ Material on this website

(such as memory managment, pointers, embedded C programming etc.)