In this article, we will discuss What is a Dangling Pointer in C? How to identify and avoid them.

What is a Dangling Pointer in C ?

A dangling pointer is a kind of pointer that points to an invalid memory location. It might be possible that a pointer, previously pointed to a valid memory location, but if memory is now deleted or unwinded, and pointer is still pointing to that invalid memory location, then it is a Dangling Pointer.

Dangling Pointer

Basically, it is a pointer that is pointing to an invalid or deallocated memory location. This can occur when the memory that the pointer was pointing to has been deleted or deallocated from the stack, but the pointer still holds the reference to that memory location. In such scenarios, we refer to the pointer as a dangling pointer.

Why Dangling Pointers are Important in C Programming ?

Dangling pointers are important to identify because if we try to access the value at the memory location through a dangling pointer, it can result in undefined behavior. It may crash the application or produce invalid or unpredictable results. Therefore, it is crucial to identify and handle dangling pointers in our code to ensure they do not exist in our application.

In this article, we will discuss three different scenarios that can cause dangling pointers. Let’s discuss them one by one.

De-Allocating Memory and Dangling Pointers

The first scenario that can cause the creation of a dangling pointer is the deallocation of memory. Suppose we allocate some memory on the heap using the malloc function and assign the location of that memory to a pointer.

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

After some time, we delete the memory by calling the free() function.

free(ptr); 

// ptr is now a Dangling Pointer

if (ptr)
{
    printf("Value is : %d \n", *ptr);
}

Output:

Undefined Behaviour

In the “free(ptr)” function call, we have freed the memory, but the pointer still points to a location where the memory has already been deleted. This makes the pointer a dangling pointer. If we try to access the value using this pointer, it can result in undefined behaviour.

To handle this scenario, it is essential to assign the pointer to NULL after freeing the memory.

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

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

    free(ptr); 
    
    // ptr is now a Dangling pointer, 
    //because it is pointing to memory that is deleted

    ptr = NULL;

    // ptr is not a dangling pointer now

    if (ptr)
    {
        printf("Value is : %d \n", *ptr);
    }
}

Once the pointer is assigned to NULL, it is no longer a dangling pointer. This is how we can identify and handle dangling pointers when deallocating memory on the heap.

Function Call and Dangling Pointers

Let’s discuss the second scenario. It is due to stack unwinding after a function call. Take a look at this example.

#include<stdio.h>

int* getValue()
{
    int value = 11;

    return &value;
}
int main()
{
    int *ptr = getValue();

    // ptr is now a dangling pointer

    if (ptr)
    {
        printf("Value is : %d \n", *ptr);
    }
    
    return 0;
}

Output:

Undefined Behaviour

In this example, we called the function getValue(). Inside this function, we allocate a variable on the local stack and return its pointer. But as soon as the function returns, the local stack of this function gets unwinded, and the memory to which this pointer is pointing becomes invalid. Here, the pointer ptr is pointing to a local variable of a function that is out of scope. This makes the pointer a dangling pointer.

If you try to access the value at this memory location, it can result in undefined behaviour. It can cause the application to crash or give unexpected results.

To avoid this scenario, we can either not return a pointer from a function that points to a local variable, or we can make the local variable static. For example,

#include<stdio.h>

int* getValue()
{
    static int value = 11;

    return &value;
}
int main()
{
    int *ptr = getValue();

    if (ptr)
    {
        printf("Value is : %d \n", *ptr);
    }
    
    return 0;
}

In the latter case, the scope of the variable will be at the program level, and once the function returns, the memory it points to will not be unwinded. Thus, we can safely use the pointer because the memory is still valid.

Code Block and Dangling Pointers

Now let’s discuss the third way in which dangling pointers can be created. Dangling pointers can be created when a variable goes out of a scope, but a pointer is still pointing to the memory location of that variable. Consider this example.

#include<stdio.h>

int main()
{
    int x = 10;
    int* ptr = NULL;

    if (x > 5)
    {
        int value = 11;
        ptr =  &value;
    }

    if (ptr)
    {
        printf("Value is : %d \n", *ptr);
    }
    
    return 0;
}

Output:

Undefined Behaviour

In the main function, we have created a separate block. When we create a separate block, the scope of this block is different from the main function, and so will be its stack. When this block exists its scope, the memory on its stack will be deallocated. In this example, the memory of variable `value` will be unwinded from the stack, when this block ends. So, the memory to which pointer `ptr` is pointing will be deallocated.

Therefore, the pointer `ptr` which stores the address of the memory location from the stack of this block becomes a dangling pointer, because the memory is now invalid. If you try to access anything using this pointer, it can result in unexpected behavior.

Summary

These were the three different scenarios where we can encounter dangling pointers in C programming. It is important to handle dangling pointers properly in your code; otherwise, your code can produce unexpected results or crash during production.

In this article, we discussed what a dangling pointer is and why it is important to identify them. We then explored three different scenarios where dangling pointers can be created in our code.

The first scenario occurs when we allocate memory on the heap and deallocate it without assigning NULL to the pointer. In this case, the pointer becomes a dangling pointer.

The second scenario arises when we call a function that returns a pointer to a local variable. Once the function exits, the local variable goes out of scope, making the pointer a dangling pointer.

The third scenario involves assigning a pointer to a memory location inside a block. When the block exits, the pointer still points to a variable or memory location that has been deallocated, resulting in a dangling pointer.

These concepts and information is applicable to both C and C++ programming.

Ritika Ohri

Hi, I am Ritika Ohri, founder of this blog. I craft comprehensive programming tutorials and also manage a YouTube channel. You can also connect with me on Linkedin.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.