Dangling Pointers in C++
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.

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++ 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++ 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++ 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++ 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.
#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++ 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
#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