I'm trying to come up with an example for a dangling pointer in C, but the code I came up with produces results that don't exactly display what I'm expecting.
#include <stdio.h>
int* dangling_ptr();
int main(void)
{
int* ptr = dangling_ptr();
printf("%d\n", *ptr); // outputs 5 to the console
return 0;
}
int* dangling_ptr()
{
int x = 5;
int* x_ptr = &x;
return x_ptr;
}
I was expecting some garbage integer value to be sitting in the memory returned, but de-referencing and printing the value displays 5 to the screen.
I know that the memory address returned by dangling_ptr()
is not valid anymore, but it's clear that the memory still hasn't been overwritten. This brings up two questions.
Is my understanding of dangling pointers here wrong? The memory should now be invalid, correct?
If I am correct in my understanding, why hasn't the OS reclaimed that memory and made it invalid? Why is the value 5 still sitting there?
CodePudding user response:
Is my understanding of dangling pointers here wrong?
Yes.
The memory should now be invalid, correct?
Depends on how you define "invalid". It is still accessible, and may contain the original, or any other value (the value it contains is undefined).
why hasn't the OS reclaimed that memory and made it invalid
You mean "inaccessible", not "invalid".
Doing so for stack operations would be exceedingly inefficient, and no OS in existence does this. This isn't done for heap either (outside of heap debug allocators), for the same reason.
In addition, OSes are limited by the capabilities of the processors they are running on, and no mainstream processor has ability to make inaccessible anything less than a full page (usually 4096 bytes or more). So even if the OS wanted to make the dangling stack inaccessible, it wouldn't be able to -- the area it would need to make inaccessible is too small.
Update:
So then would this not be a dangling pointer?
Yes, this is a dangling stack pointer.
My understanding is that the function dangling_ptr() allocates memory for x on the stack and returns the address of that memory.
Correct.
Once dangling_ptr() terminates, all the memory reserved via that stack frame is freed and now no longer reliable to refer to.
Correct in that you should no longer read or write that memory.
Incorrect in that nothing is free
d here -- the memory is still on the stack, it's just in the unallocated part of the stack.
Where am I going wrong in my understanding there?
You believe that once the memory is unallocated, something definitive should happen when you access it.
But what actually happens is undefined -- anything can happen. Among the things which could happen: you could read the original value, you could read some other value, your program may crash (this outcome is unlikely on most OSes for reasons stated above).