A dangling pointer is a pointer that points to a memory location that is invalid. It might be possible that the memory pointer was pointing to a memory location that used to be valid, but as of now, it is invalid. There can be multiple instances when a pointer can become a dangling pointer. Let’s discuss them one by one.
Suppose we call a function. Inside the function, we declare a variable on the stack like this,
int * getData() { int num = 10; int * ptr = # return ptr; }
So memory for this variable num
will be allocated in the stack of this function. Then we create a pointer ptr
pointing to the address location of this variable. This pointer to integer is pointing to a memory location that is in the stack of this function. Now, when this function ends, in the return value of this function, we are returning this pointer.
But, when this function ends, and the getData() returns, stack unwinding happens, and the memory allocated for the variable num
will be deallocated from the stack. However, the pointer ptr
, which we have returned, is still pointing to that memory location. So, after the function call getData()
, the pointer ptr
becomes a dangling pointer.
If you try to access the memory or data at the memory location using this pointer ptr
, it results in an unexpected behaviour. Like this,
int * ptr = getData(); // Pointer ptr is a dangling pointer std::cout<< *ptr ; // Undefine behaviour
Output:
Crash or another Undefined Behaviour
The pointer ptr
is a dangling pointer and points to an invalid memory location, and we are trying to access the memory or data at that location. It can result in a crash or some other undefined behaviour, we dont know what is now at that memory location.
Another scenario is when we allocate memory on the heap using the new
operator and initialise the pointer ptr
with the address of that memory location. But after some time, we delete that memory using the pointer ptr
.
#include <iostream> int main() { int * ptr = new int(22); std::cout<< *ptr ; delete ptr; // Pointer ptr is now a Dangling pointer std::cout<< *ptr ; // Undefine Behaviour return 0; }
Output:
Crash or another Undefined Behaviour
Once the pointer ptr
is deleted by the delete
operation, the pointer ptr
becomes a dangling pointer, because it is still pointing to a memory location that is already deleted. Now, if someone tries to access the data at this memory location using the pointer ptr
, it can result in unexpected behaviour. It is like this, because the pointer ptr
is pointing to an invalid memory location. To avoid this case, we should always assign nullptr
or NULL
to a pointer after calling the delete
operator on it.
The third scenario is regarding a block. Checkout this example,
#include <iostream> int main() { int * ptr = nullptr; if(true) { int num = 11; ptr = # } // Pointer `ptr` is now a Dangling pointer std::cout<< *ptr ; // Undefine Behaviour return 0; }
Output:
Crash or another Undefined Behaviour
Suppose we start a if block and, inside the block, we create a variable integer num
. Now, we initialise the pointer ptr
with the address of this variable num
. After that, we exited the if-block. The integer variable was declared inside the block, so when this block exits, stack unwinding happens for this block, and the memory for the variable num
goes out of scope. But the pointer ptr
is still pointing to that memory location. Therefor, when the if-block ends, the pointer ptr
becomes a dangling pointer. If someone tries to access the data at that memory location using the pointer ptr
after the block ends, it can result in unexpected behaviour or even crash your application.
So these were the three different ways where we can encounter a dangling pointer in C or C++.
To avoid Dangling Pointers, we must follow some rules i.e.
We need to keep these points in mind while doing memory management in our programs to avoid dangling pointers and undefined behaviours in C++.