What is a dangling pointer?
Asked Answered
I

8

76

I don't understand concept of dangling pointer, was googling around, and writing test methods to find one.

I just wonder is this a dangling pointer? As whatever example I found was returning something, here I'm trying something similar!

void foo(const std::string name)
{
    // will it be Dangling pointer?!, with comments/Answer
    // it could be if in new_foo, I store name into Global.
    // Why?! And what is safe then?
    new_foo(name.c_str());
}

void new_foo(const char* name)
{
    // print name or do something with name...   
}
Idolater answered 1/8, 2013 at 14:45 Comment(7)
"will it be Dangling pointer?!, with comments/Answer it is" -- No, it is not. There is no dangling pointer in your first example. What you are doing there is perfectly, 100% safe and correct.Cinquain
I don't see how you can have a dangling pointer ... without the pointer.Longboat
@TheOtherGuy I mean, no const char* ... carrying same const std::stringIdolater
@BenjaminLindley well, form Jack's answer, it seems like true, as c_str() returns pointer to string, which may not be valid in new_foo .... could be wrong!!Idolater
@codemuncher: Re-read Jack's answer. Basically, as long as you're not using new_foo to store the pointer in a place more global than foo, you should be safe.Cinquain
Not dangling because name doesn't disappear until foo exits, which is after new_foo exits. A similar example that is dangling might be: const char *foo(string name) { return name.c_str(); }, because name disappears when foo exitsYance
Note: I edited the return type of foo so as not to look foolish for saying that what you are doing is 100% safe and correct.Cinquain
C
89

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.

Careaga answered 1/8, 2013 at 14:48 Comment(20)
IIRC if you modify the content of the string then you invalidate the pointer returned by c_str() so it could be considered dangling.Careaga
But the string isn't modified. And there's no way for it to be legally modified, even in a multi-threaded application.Cinquain
@Careaga so you mean, if I modify string name in new_foo it could be dangling? and if I use name in foo its fine?Idolater
@BenjaminLindley: thing about name.push_back('f'), if appending the character requires a realloc of the string internal buffer then the pointer could become invalid.Careaga
@BenjaminLindley: but it is necessary to know about the fact that storing the c string from a std::string without copying it is not always safe, and why it is so.Careaga
@BenjaminLindley ... and reckless and unnecessarily unsafe. Working around std::string with strdup is just ridiculous.Milksop
@Careaga How on earth could new_foo access the function parameter of foo to modify it? The OP's example is safe.Sexagesimal
@Angew: in his example it says "... print name or do something with name...". According to me this means that the pointer could be stored somewhere and expected to be valid after that the string has been destroyed. Actually no one can be sure of it without knowing the actual code, I just made a wider assumption.Careaga
Ok, can anyone, modify my first code, so that its actually a dangling pointer ...thanks!Idolater
@BenjaminLindley awesome!! one more question, why its dangling?! and what is safe? thanks!Idolater
@codemuncher: Does Jack's answer not explain that? Please read it carefully, because it does.Cinquain
@BenjaminLindley ... help me here... if I destroy global pointer( global_name in your example) then why its dangling .. i'm not with my routine (new_foo) ... or you mean if I free name in new_foo routine, then global_name is dangling pointer?Idolater
@codemuncher: global_name becomes a dangling pointer when foo returns, because the string from which the pointer originated (string name in foo) is destroyed at that time.Cinquain
Just a nit concerning the first sentence. A dangling pointer doesn't point to data which is invalid; it is the pointer itself that is invalid. (In other words, it doesn't point to data, period.) Just copying the pointer is undefined behavior.Virelay
@BenjaminLindley if I copied it with strdup ... instead of assignment in new_foo ... then it would be fine right? Or if I just keep passing const std::string ? Sorry if its again obvious for you guys!Idolater
@JamesKanze well I tried to run code given by Benjamin ... in main just calling foo("CodeMuncher") and print global_name .. it prints! So dangling pointer is like "your prog might crash because of that" is it?Idolater
@codemuncher A dangling pointer is undefined behavior if there is any lvalue to rvalue conversion on it. In other words, you can assign to it, but you cannot assign from it, or return it. Of course, undefined behavior can do anything. Including nothing. On most modern machines, I wouldn't expect problems until trying to dereference the pointer, and not necessarily even then. (I have worked on a system where returning such a pointer would cause the process to crash. Intel 80386, running I forget which OS, but it was some real time kernel which handled 48 bit addresses.)Virelay
@JamesKanze gotcha .. what is "safe" then? Lets say I want to do assignment (like one in question - global) or one how Jack suggested .. OOP one. How to do those things "safely"?Idolater
@codemuncher I'm not sure what you want to do "safely". The rule is simple: all pointers must be either null or point to a valid "object". (I'm using "object" in the sense it is used in the C++ standard.) When you delete something, you must ensure (by design) that no pointers to it continue to exist. And with regards to the return value of std::string::c_str(): the only time you should use this function is when interfacing to a legacy function which requires a char const*.Virelay
I guess the word dangling is used because the pointer used to be connected to something solid (an allocated block of memory), but the object was cut away and the memory was released. The result is a dangling pointer that no longer is connected to anythingDingy
P
16

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.

Popliteal answered 1/8, 2013 at 14:50 Comment(3)
@Miklós Homolya its "const " .. what do you mean modify in new_foo?!Idolater
That use of "const" is (compiler) front-end feature, which could be overcome by a const_cast. The problem is how to get - in a standard compliant way - a reference to the stack variable 'name', because the code of function 'foo' is already given.Popliteal
I don't think new_foo can change the nameTericaterina
G
13

Taken from here. Although, even if this is for C, it is the same for C++.

Dangling Pointer

When a pointer is pointing at the memory address of a variable but after some time that variable is deleted from that memory location while the pointer is still pointing to it, then such a pointer is known as a dangling pointer and this problem is known as the dangling pointer problem.

Initially

enter image description here

Later

enter image description here

Example

#include<stdio.h>

int *call();
int main() {

  int *ptr;
  ptr = call();

  fflush(stdin);
  printf("%d", *ptr);
  return 0;
}

int * call() {
  int x=25;
  ++x;

  return &x;
}

Its output will be garbage because the variable x is a local variable. Its scope and lifetime are within the function call hence after returning the address of x variable x becomes dead and the pointer is still pointing to that location.

Gschu answered 22/1, 2016 at 11:5 Comment(2)
The 'dangling pointer' is one of the most pernicious problems in C, and is one reason C++ created references. Sadly, references can become dangling in the same way. Smart pointers (en.wikipedia.org/wiki/Smart_pointer) are one way of dealing with the problem. Unfortunately the ensuing behavior is undefined, so that sometimes the result will become 'garbage' (if another part of the program uses that area of memory), and sometimes it will not. This leads to the kind of difficult to replicate bug that makes people tear their hair out.Hindemith
@Yatin, you edited a citation, though it's not in the citation format it does have the link where it was taken from, please be careful with that.Statocyst
A
9

As a matter of style, I explain a dangling pointer as "a pointer which still exists, even though the object it pointed to no longer exists".

In your case, the pointer name exists for a shorter period that the object that it points to. So it's never dangling.

Inside common C++ classes, pointers dangle for a very short period, inside destructors. That's because the delete statement is before the last } of the destructor, while the pointer itself ceases to exist at the last }. If you don't want to worry about this, use e.g. unique_ptr<T>. The T* pointer will dangle for a very short time inside the unique_ptr::~unique_ptr destructor, which is perfectly safe.

Appenzell answered 2/8, 2013 at 7:49 Comment(0)
G
7

Dangling pointers is a situation where you have valid pointers in the stack, but it is pointing to invalid memory. You might end up in this situation when you deallocate the heap memory before the pointers in stack deallocated.

This is a security issue. Because when you deallocate a memory, we are informing Operating System, that we no longer need this section of memory. So OS will mark that piece of memory as ready to allocate and allocate to other applications when they request for memory.

Usually, in C++, memory allocated and deallocated through a general pattern. Constructor in a class gets invoked when a class initialised and this is the right place to allocate memory in heap.Destructor will be invoked when the class instance goes out of scope, and this is the right place to deallocate memory from heap. Assume we already created a class that does allocation and deallocation of memory in constructor and destructor respectively.

int main() {
  SomeClass pointer1 = SomeClass();
  SomeClass pointer2 = pointer1;
}

In the above example code, there are two variables declared but both holding the same value. When the constructor invoked, it allocates a heap memory. Then we are declaring one more variable and assigning the same value. In C++ usually, when you assign a value of complex type, it does a shallow copy (unless you explicitly implemented copy constructor) instead of deep copy. That means the only pointer gets copied in Stack, but not the heap memory. Actually it is not recommended to copy heap memory for performance reasons. Now the final memory layout looks like that we have two pointers pointing to the same heap memory.

Now when the function is done with execution, local variables goes out of scope and it invokes destructor. First, pointer2 invokes destructor that deallocates the heap memory. At this point, pointer1 becomes dangling pointer. It points to a memory that is already deallocated.

From this example, we understood that the primary cause of dangling pointer is having multiple owners for the same resource. Because when one pointer deallocates memory other pointers became dangling pointers.

Globular answered 12/11, 2019 at 7:49 Comment(0)
D
3

//Declaring two pointer variables to int
int * ptr1;
int * ptr2;
// Allocating dynamic memory in the heap
ptr1 = new int;
ptr2 = ptr1; // Having both pointers to point same dynamic memory location
//deleting the dynamic memory location 
delete ptr1;
ptr1 = nullptr; 
//ptr2 is still pointing the already deleted memory location 
//We call ptr2 is a dangling pointer
Deaton answered 30/6, 2020 at 15:11 Comment(0)
R
0

A pointer containing a address which is not present or it has been deleted.

In simple way we can say that pointer is containing the address of a location whose memory has been deleted.

You can understand it with a simple diagram:-

Dangling pointer

Rhodia answered 10/4, 2023 at 2:56 Comment(0)
A
-2

Dangling Pointer and dangling pointer problem If any pointer is pointing the memory address of any variable but after some variable has deleted from that memory location while pointer is still pointing such memory location.

That pointer is called as dangling pointer and the problem that arises at that time is called as dangling pointer problem.

Here are some examples: Dangling Pointer and dangling pointer problem

Aztec answered 26/7, 2016 at 9:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.