What Is a Dangling Pointer

What is a dangling pointer?

A dangling pointer is a pointer that points to invalid data or to data which is not valid anymore, for example:

Class *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:

Object *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.

Dangling pointers in C

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:

#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:

before: 0x561b73d3b260
after: 0x561b73d3b260
before: 0x561b73d3b260
after: 0x561b73d3b260

Dangling pointers

A dangling pointer is a pointer that points to a location in memory where there was an object but that object is already gone.

A dangling pointer is nothing useful or desirable, it rather describes that the pointer is completely useless and you probably have a logic error in your code.

Consider this:

int* x;
{
int y = 4;
x = &y;
}
*x = 42; // BOOOM !! Dont do this !! Undefined behavior !!

After closing the scope (}) the object x points to does no longer exists. x will not automagically be set to NULL or anything the like. There is no y at the memory location x was pointing to. The official terminology is that after closing the scope x has a invalid pointer value in C++ and in C the value of the pointer is indeterminate.

On the other hand, if you do not dereference x after y is gone, there is no problem. x is still a dangling pointer but you can simply assign something else to make it point to some object again:

int* x;
{
int y = 4;
x = &y;
} // <- x can be said to be dangling here, but who cares?
int z = 5;
x = &z; // <- x again points to an object

C++ Dangling Pointers and Memory Leaks

The rules of the game:

  • For every new Type draw a box. Put a question in the box (you don't know what is in there).
  • For every delete p cross out the box pointed to by p.
  • For every a = b (where there are no stars) draw a line from variable a to a box b.
  • For every *x = y write y inside the box pointed at by x.
  • For every *x = *y read the content of the box y and put a copy in x

The result:

  • When you have a box with no variables pointing at it you have a leak.
  • If you have a pointer that does not point at a box (or a crossed out box) you have a dangling pointer.

The first problem:

ptrA = new int;
ptrB = new int;
*ptrA = 345;
ptrB = ptrA;

Lets do this line by line:

ptrA = new int;

// Part 1 has a new so draw a box
*********
* ? *
*********

// Part 2 assignment to variable add a line
ptrA -------> *********
* ? *
*********

ptrB = new int;

// Part 3 has a new so draw another box
ptrA -------> *********
* ? *
*********

*********
* ? *
*********

// Part 4 assignment to variable add a line

ptrA -------> *********
* ? *
*********

ptrB -------> *********
* ? *
*********

*ptrA = 345;

ptrA -------> *********
* 345 *
*********

ptrB -------> *********
* ? *
*********

ptrB = ptrA;

ptrA -------> *********
| * 345 *
| *********
|
ptrB ---- *********
* ? *
*********

Seems like you have a leaked box. i.e. There is a box with no variable pointing at it.

What is the difference between a dangling pointer and memory leak?

What is the difference between a dangling pointer and memory leak?

You could say a dangling pointer is the opposite of a memory leak.

One is a pointer that doesn't point to valid memory, and one is valid memory that nothing points to.

(But as the other answers point out, your code is neither.)

Difference between dangling pointer and memory leak

A dangling pointer points to memory that has already been freed. The storage is no longer allocated. Trying to access it might cause a Segmentation fault.

Common way to end up with a dangling pointer:

char *func()
{
char str[10];
strcpy(str, "Hello!");
return str;
}
//returned pointer points to str which has gone out of scope.

You are returning an address which was a local variable, which would have gone out of scope by the time control was returned to the calling function. (Undefined behaviour)

Another common dangling pointer example is an access of a memory location via pointer, after free has been explicitly called on that memory.

int *c = malloc(sizeof(int));
free(c);
*c = 3; //writing to freed location!

A memory leak is memory which hasn't been freed, there is no way to access (or free it) now, as there are no ways to get to it anymore. (E.g. a pointer which was the only reference to a memory location dynamically allocated (and not freed) which points somewhere else now.)

void func(){
char *ch = malloc(10);
}
//ch not valid outside, no way to access malloc-ed memory

Char-ptr ch is a local variable that goes out of scope at the end of the function, leaking the dynamically allocated 10 bytes.

Dangling pointer example still outputting valid data

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 freed 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).

What is the difference between garbage and dangling references?

A dangling reference is a reference to an object that no longer exists. Garbage is an object that cannot be reached through a reference.

Dangling references do not exist in garbage collected languages because objects are only reclaimed when they are no longer accessible (only garbage is collected). In some languages or framework, you can use "weak references", which can be left dangling since they are not considered during collection passes.

In languages with manual memory management, like C or C++, you can encounter dangling pointers, by doing this for instance:

int * p = new int;
delete p;

int i = *p; // error, p has been deleted!

Is this a dangling pointer?

x is an array declared like

int x[3] = {1, 2, 3};

So it can not be a dangling pointer. Objects of array types are not pointers.

In this declaration

int *y = x;

the array designator x used as an initializing expression is implicitly converted to a pointer to its first element and this pointer is not an lvalue. After this declaration the initializing expression will not be alive.

So there is no dangling pointer in the presented program.

Pay attention to that this statement

*y = null;

is invalid. It seems you mean

y = NULL;

Now the variable y is a null pointer.

Here is an example of a dangling pointer.

int *p = malloc( sizeof( *p ) );
free( p );

After the call of free the pointer p is a dangling pointer. It does not point to a valid object.



Related Topics



Leave a reply



Submit