Open In App

Dangling Pointers in C++

Last Updated : 04 Jun, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

In C++, pointers can be used for various purposes such as storing the address of a variable, allocated objects on the heap, passing functions to other functions, iterating over elements in arrays, and so on. But many problems arise when pointers are not handled properly. In this article, we will learn about dangling pointers, how they occur and how to deal with them.

Dangling-Pointer-in-Programming
Dangling Pointer in C++


What is a Dangling Pointer in C++?

In C language, a pointer that points to a memory location that has been deallocated earlier in the program is called Dangling Pointer.

A dangling pointer is a very common occurrence that generally occurs when we use the 'delete' to deallocate memory that was previously allocated and the pointer that was pointing to that memory still points to the same address. There are also other cases which leads to the pointer being the dangling pointer:

Cases that Leads to Dangling Pointer in C++

  • Deallocation of Memory using delete or free().
  • Referencing the Local Variable of the function after it is executed.
  • Variable goes out of scope.

For Example

int* ptr = new int(5);
delete ptr; // ptr now becomes a dangling pointer

Examples of Dangling Pointer in C++

Example 1: Dangling Pointer by Memory Deallocation using delete.

The below program demonstrates how a pointer becomes a dangling pointer when the dynamic memory is deallocated using delete or in C++.

C++
// C++ program demonstrating how a dangling pointer is
// created
#include <iostream>
using namespace std;

int main()
{
    // Allocating memory
    int* ptr = new int(5);

    // Deallocating memory
    delete ptr;

    // Now, ptr becomes a dangling pointer
    cout << "ptr is now a dangling pointer" << endl;

    return 0;
}

Output
ptr is now a dangling pointer

Example 2: Dangling Pointer Created by Accessing Local Variable of Function After its Execution

C++
// C++ program to demonstrate how the accessing of functions
// local variable after it is executed results in dangling
// pointer
#include <stdio.h>

int* getDanglingPointer()
{
    int localVar = 42;
    // Returning the address of a local variable
    return &localVar;
}

int main()
{
    int* danglingPtr = getDanglingPointer();
    // Undefined behavior
    printf("Value of dangling pointer: %d\n", *danglingPtr);
    return 0;
}


Output

{Segmentation Fault}

Example 3: Dangling Pointer Created by Accessing Variable Out of Scope.

C++
// C++ program to demonstrate how the accessing a variable
// outisde its scope results in dangling pointer
#include <stdio.h>

int main()
{
    int* danglingPtr;

    // block scope
    {
        int var = 210;
        danglingPtr = &var;
    }
    // Undefined behavior
    printf("Value of dangling pointer: %d\n", *danglingPtr);
    return 0;
}


The above program will lead to undefined behaviour or segmentation fault or you can also get the value of the variable. It is unpredictable.

Why is it important to handle Dangling Pointers?

Handling dangling pointers is important for maintaining the integrity and stability of a program. If a program attempts to access or modify the memory through a dangling pointer, it can lead to unpredictable behaviour, including crashes and data corruption as shown by the above examples.

By handling dangling pointers properly, we can improve the reliability and security of the program and prevent any unpredictable access to any memory location.

How to Handle Dangling Pointers in C++?

The methods of handling dangling pointers vary depending on the cases it is being created. Following is the list of all the methods using which we can prevent the dangling pointers:

1. Assign NULL or nullptr to the Pointers that are Not in Use

Make a habit that, whenever we are done with the pointer, always assign it to NULL or nullptr and whenever you access any variable, we can check if the pointer is NULL or nullptr and then access it.

C++
// C++ program to illustrate how to handle null pointer.
#include <iostream>
using namespace std;

int main()
{
    // allocating memory
    int* value = new int(11);

    // freeing it
    delete value;

    // assigning null
    value = nullptr;

    // checking null before accessing value
    if (value == nullptr) {
        cout << "Memory is deallocated." << endl;
    }
    else {
        cout << "Value: " << value << endl;
    }
    return 0;
}

Output
Memory is deallocated.

2. Using Smart Pointers

Smart pointers are the new feature of C++ 11 that are the wrapper classes over the raw pointer. These pointer are specifically designed to avoid all these cases of dangling pointers along with other common pointer risks and errors.

C++
#include <iostream>
#include <memory>
using namespace std;

// Function returns a smart pointer
shared_ptr<int> getSmartPointer()
{
    return make_shared<int>(42); // Return a smart pointer
}

int main()
{
    // Call the function and store the returned smart
    // pointer
    shared_ptr<int> ptr = getSmartPointer();
    cout << "Value: " << *ptr << endl;
    // Smart pointer automatically handles memory
    // deallocation
    return 0;
}

Output
Value: 42

To learn more about them, refer to the article - Smart Pointer in C++

3. Use Dynamic Memory Allocation for the Local Variables that are to be returned.

The memory allocated using new or malloc in C++ will not be deallocated till we do it manually using delete or free(). We can use this type of memory for local variables of a function that we want to return to the caller function.

Example:

C++
// C++ Program to illustrate how to return dynamically
// created funtion's local variable.
#include <iostream>
using namespace std;

int* getPointer()
{
    // Allocate on the heap
    int* localVar = new int(42);
    return localVar;
}

int main()
{

    // getting the pointer to the variable
    int* ptr = getPointer();
    cout << "Value: " << *ptr << endl;

    // manually deallocating it
    delete ptr;
    // setting ptr to null
    ptr = NULL;
    return 0;
}

Output
Value: 42

4. Using References instead of Pointers

References are builtin features in C++ and are the variables that reference the another variables. The references are safer as compared to pointers but we cannot use them to replace pointers in all cases. So, we should use it wherever it is possible to use instead of pointers.

Example

C++
#include <iostream>
using namespace std;

int& getReference()
{
    // Use static to extend the lifetime
    static int localVar = 42;
    return localVar;
}

int main()
{
    int& ref = getReference();
    cout << "Value: " << ref << endl;
    return 0;
}

Output
Value: 42



Next Article
Practice Tags :

Similar Reads