Dangling pointers are only a concern if you try to use them after you've freed them.
Yes, it's possible that a new allocation can return the same address that x has. But you can never know whether this is going to happen, so you still can't use x any more. It would just be a coincidence if its address became valid again.
Even if you keep allocating and freeing the same size, there's no expectation that it will keep reusing the same address.
For safety you must assume that a freed pointer will never become valid again.
Answer from Barmar on Stack OverflowDangling pointers in C - Stack Overflow
c++ - What is a dangling pointer? - Stack Overflow
Dangling Pointer in C - Stack Overflow
Dangling Pointers
Can the compiler detect a dangling pointer in C?
What causes dangling pointers in C?
What are the risks of using a dangling pointer in C?
Videos
The lecture notes of my professor mention that when u deference a dangling pointer, you would get an error, but I am not getting error, rather different answers on different compilers, what's happening here?
Dangling pointers are only a concern if you try to use them after you've freed them.
Yes, it's possible that a new allocation can return the same address that x has. But you can never know whether this is going to happen, so you still can't use x any more. It would just be a coincidence if its address became valid again.
Even if you keep allocating and freeing the same size, there's no expectation that it will keep reusing the same address.
For safety you must assume that a freed pointer will never become valid again.
The term dangling pointer means that whatever address in memory it points to is invalid. If you make it valid, like your 2nd malloc, then the address becomes valid. If you store the same address in two different variables (via your assumption) both are valid pointers:
Copy#include <stdio.h>
#include <stdlib.h>
struct s { int i; };
int main() {
struct s *p = malloc(sizeof(struct s));
printf("before: %p\n", (void *) p);
free(p);
// p is dangling
printf("after: %p\n", p);
struct s *p2 = malloc(sizeof(struct s));
// p and p2 are valid
printf("before: %p\n", (void *) p2);
free(p2);
// p and p2 are dangling
printf("after: %p\n", p2);
}
and the output from my pleasingly corroborative malloc:
Copybefore: 0x561b73d3b260
after: 0x561b73d3b260
before: 0x561b73d3b260
after: 0x561b73d3b260
A dangling pointer is a pointer that points to invalid data or to data which is not valid anymore, for example:
CopyClass *object = new Class();
Class *object2 = object;
delete object;
object = nullptr;
// now object2 points to something which is not valid anymore
This can occur even in stack allocated objects:
CopyObject *method() {
Object object;
return &object;
}
Object *object2 = method();
// object2 points to an object which has been removed from stack after exiting the function
The pointer returned by c_str may become invalid if the string is modified afterwards or destroyed. In your example you don't seem to modify it, but since it's not clear what you are going to do with const char *name it's impossible to know it your code is inherently safe or not.
For example, if you store the pointer somewhere and then the corresponding string is destroyed, the pointer becomes invalid. If you use const char *name just in the scope of new_foo (for example, for printing purposes) then the pointer will remain valid.
A dangling pointer is a (non-NULL) pointer which points to unallocated (already freed) memory area.
The above example should be correct given that the string is not modified through new_foo.
Undefined Behavior means anything can happen, including it'll do as you expect. Your stack variables weren't overwritten in this case.
void func3() {
int a=0, b=1, c=2;
}
If you include a call to func3() in between func1 and printf you'll get a different result.
EDIT: What actually happens on some platforms.
int *func(void)
{
int num;
num = 100;
return #
}
Let's assume, for simplicity, that the stack pointer is 10 before you call this function, and that the stack grows upwards.
When you call the function, the return address is pushed on stack (at position 10) and the stack pointer is incremented to 14 (yes, very simplified). The variable num is then created on stack at position 14, and the stack pointer is incremented to 18.
When you return, you return a pointer to address 14 - return address is popped from stack and the stack pointer is back to 10.
void func2() {
int y = 1;
}
Here, the same thing happens. Return address pushed at position, y created at position 14, you assign 1 to y (writes to address 14), you return and stack pointer's back to position 10.
Now, your old int * returned from func points to address 14, and the last modification made to that address was func2's local variable assignment. So, you have a dangling pointer (nothing above position 10 in stack is valid) that points to a left-over value from the call to func2
It's because of the way the memory gets allocated.
After calling func and returning a dangling pointer, the part of the stack where num was stored still has the value 100 (which is what you are seeing afterwards). We can reach that conclusion based on the observed behavior.
After the change, it looks like what happens is that the func1 call overwrites the memory location that a points to with the result of the addition inside func1 (the stack space previously used for func is reused now by func1), so that's why you see 200.
Of course, all of this is undefined behavior so while this might be a good philosophical question, answering it doesn't really buy you anything.