Multiple pointers to the same object - deletion

Started by
10 comments, last by Ravyne 14 years, 5 months ago
Hey , I just want to clarify if what I presume is true. Given the following:

class Foo
{
  /......./
};

int main()
{
  Foo *p = new Foo();
  Foo *p1 = p;
  Foo *p2 = p;
  Foo *p3 = p;

  delete p;
}


I know that the delete operator actually deletes the object the pointer is pointing to , so what happens to the 3 other pointers pointing to the that object? Are they now pointing to NULL or to nothing at all? Now consider this example:


// FooList1.h
 vector<Foo*> FooList1;

// FooList2.h
 vector<Foo*> FooList2;


A pointer in FooList1 points to the same object that a pointer in FooList2 points to. If I empty one of the containers and delete all of it's pointers , does this mean that all of the pointers in the other container will become invalid and 'dangerous' to use because they will point to nothing? Lastly , a pointer that points to nothing , it has it's own address and memory location. Does the OS clean up pointers like that so it wont be considered as a memory leak?
Advertisement
They are now dangling pointers. Their value doesn't change only the value pointed at does. deleting or dereferencing them is illegal.
Quote:
so what happens to the 3 other pointers pointing to the that object? Are they now pointing to NULL or to nothing at all?

They're pointing to unallocated memory (effectively, to garbage).

Quote:
If I empty one of the containers and delete all of it's pointers , does this mean that all of the pointers in the other container will become invalid and 'dangerous' to use because they will point to nothing?

They will all point to unallocated memory, yes (not to "nothing").

Quote:
Lastly , a pointer that points to nothing , it has it's own address and memory location. Does the OS clean up pointers like that so it wont be considered as a memory leak?

A "pointer that points to nothing" is more commonly called the null pointer; it's not pointing to allocated memory so there is nothing to leak.

Your OS will typically, via one means or another, "release" the memory you may leak at the end of the program, but that's not something you should rely on, and does not prevent all issues.
So in C or C++ it helps to not think of pointers as tethers to the objects to which they point. Pointers are just memory addresses where the object can be found. So if you call delete on a pointer, it just frees the memory at the address stored in the pointer. Other pointers with the same address are still pointing to the same place in memory where the object used to be, but that object just isn't there anymore.

It's like if I move and don't tell my friends. My old address is still a real address, I just don't live there anymore. So they're gonna be bummed when they drop by to say hi and some 80yr old WWII vet answers the door with a shotgun.

-me
Thank's for the quick replies!
So to prevent errors with dangling pointers I just assign them to point to NULL , or otherwise just use a reference - counting smart pointer.
Well, a "null" (well, null is apparently just a macro for 0) value for a pointer might be easier for you to manage, but you still have to make sure your code doesn't dereference it.
Quote:Original post by Xsy
Thank's for the quick replies!
So to prevent errors with dangling pointers I just assign them to point to NULL , or otherwise just use a reference - counting smart pointer.

Ideally, you will write your program so dangling references are impossible. In some cases, this will involve using smart pointers. In others, correctly scoping the variables might be sufficient.

NULL pointers should be reserved for things that are optional, by design. NULL is an extra corner case that the code has to manage, if you can write your programs such that your (smart) pointers always point to something valid then you can reduce the number of mistakes you can make.

In fact, to be clearer in intent you might use boost::optional<> rather than a nullable pointer to indicate where a value might be absent.
Quote:Original post by Xsy
Thank's for the quick replies!
So to prevent errors with dangling pointers I just assign them to point to NULL , or otherwise just use a reference - counting smart pointer.


Setting them to null or another invalid memory address (e.g. -1 or 0xDEADBEEF) is a good idea. This way, if you try to dereference them, you will get an instant access violation, which may save you tons of debugging time down the road. Note that dereferencing a regular dangling pointer may or may not crash; it can cause invisible random heap corruption; and it can pose a security risk.

Using "smart" pointers is generally a good idea, but they come with their own set of problems. Using a managed, garbage collected language is usually an even better idea (but I'm going to be flamed if I suggest this, so I won't). :) Of course, the best solution would be to use a language which cannot have dangling pointers / null references by design, like Ocaml - but suggesting that on gamedev would be akin to throwing petroleum into a raging fire...

[OpenTK: C# OpenGL 4.4, OpenGL ES 3.0 and OpenAL 1.1. Now with Linux/KMS support!]

something like shared_ptr is very useful here, though you have to be careful when you copy the address out of a shared_ptr -- If you call delete on the normal pointer the shared_ptrs will dangle, and if all the shared pointer are deleted / go out of scope, the regular pointer will then dangle.

Also, and perhaps this was corrected in some of the interceding posts, but from your original post it appears as though you may be under the belief that calling delete on a pointer sets it to a safe value (eg NULL). This is not the case, after you call delete on a pointer, that same pointer still points to where the object was. That's why the idiom is to set a deleted pointer to NULL (or 0) immediately after calling delete on it.

throw table_exception("(? ???)? ? ???");

Quote:Original post by Fiddler
Setting them to null or another invalid memory address (e.g. -1 or 0xDEADBEEF) is a good idea. This way, if you try to dereference them, you will get an instant access violation, which may save you tons of debugging time down the road. Note that dereferencing a regular dangling pointer may or may not crash; it can cause invisible random heap corruption; and it can pose a security risk.

Using "smart" pointers is generally a good idea, but they come with their own set of problems. Using a managed, garbage collected language is usually an even better idea (but I'm going to be flamed if I suggest this, so I won't). :) Of course, the best solution would be to use a language which cannot have dangling pointers / null references by design, like Ocaml - but suggesting that on gamedev would be akin to throwing petroleum into a raging fire...

Damn right - none of these languages you speak of are suitable for OS development; and won't your face be red when 0xDEADBEEF starts falling within valid memory range...

Oh, hang on - you tell me he's probably writing video games? Disregard. >_>

This topic is closed to new replies.

Advertisement