|
-
January 15th, 2010, 05:27 PM
#1
question on "delete"
Suppose I have a pointer p like this
int *p = new int(0);
*p = 100;
when I try to free the memory, I can do
delete p;
I learned that it safe "delete" a 0 (NULL) pointer, but it's undefined behavior to "delete" a pointer twice. So they told me to always add "p=0;" after deleting p.
Here comes my question:
It seems that we can just add "p=0" into the implementation of the "delete" operator in order to save some typing for coder and it's much safer. But so far it's not the case. So I am wondering why it's not and what's side effect of this addition. Thank you very much.
-
January 15th, 2010, 06:43 PM
#2
Re: question on "delete"
C++ is not designed to be safe, it's designed to do exactly what you tell it to. You can simply do this:
Code:
#define DELETE(ptr);\
{\
delete ptr;\
ptr = 0;\
}
Code:
foo * bar = new foo();
DELETE(bar);
Last edited by ninja9578; January 15th, 2010 at 06:46 PM.
-
January 15th, 2010, 08:21 PM
#3
Re: question on "delete"
 Originally Posted by ninja9578
C++ is not designed to be safe, it's designed to do exactly what you tell it to.
Not entirely true. That's certainly the philosophy of C; but C++ has embraced a policy emphasizing safety from the start, and enhancements like the STL only take things further in that direction. Lots of stuff is kept "under the hood" to make your code safer.
That said, the reason why is fairly simple: The delete operator takes a pointer by value. Just like any pointer passed by value, the function can modify what it points to (in this case, an allocated memory block), but it cannot modify the pointer itself in any way visible to the caller.
Could the language have been written so that delete took the pointer by reference instead? Yeah, probably. But there were reasons why that seemed like a bad idea, I'm sure.
The safest policy is to design your code so that you never have to call delete. I'm not endorsing memory leaks; but usage of STL containers can reduce most of your need to call "new", and usage of smart pointers can remove your need to explicitly call delete even when you do call new. Together, STL containers and smart pointers will make your code infinitely easier to maintain.
-
January 15th, 2010, 10:57 PM
#4
Re: question on "delete"
 Originally Posted by Lindley
Not entirely true. That's certainly the philosophy of C; but C++ has embraced a policy emphasizing safety from the start, and enhancements like the STL only take things further in that direction. Lots of stuff is kept "under the hood" to make your code safer.
That said, the reason why is fairly simple: The delete operator takes a pointer by value. Just like any pointer passed by value, the function can modify what it points to (in this case, an allocated memory block), but it cannot modify the pointer itself in any way visible to the caller.
Could the language have been written so that delete took the pointer by reference instead? Yeah, probably. But there were reasons why that seemed like a bad idea, I'm sure.
The safest policy is to design your code so that you never have to call delete. I'm not endorsing memory leaks; but usage of STL containers can reduce most of your need to call "new", and usage of smart pointers can remove your need to explicitly call delete even when you do call new. Together, STL containers and smart pointers will make your code infinitely easier to maintain.
Actually in the afternoon I happened to remember that C++ passed p by value...But your comment is very enlightening. Thank you very much.
P.S. I also thought about this. suppose I happened to define pp = p; then in some place I delete p and set it to 0, but chances are that I will delete pp if I couldn't remember the above definition. In this case, p =0 won't help, I will still get an undefined behavior.
-
January 15th, 2010, 11:43 PM
#5
Re: question on "delete"
Yes, aliasing (two pointers directed at the same object) is certainly a problem you need to deal with. The typical solution to that is reference counting, such as is done by the std::tr1::shared_ptr smart pointer class. Only when the reference count reaches 0 does the object finally get destroyed.
-
January 22nd, 2010, 04:49 AM
#6
Re: question on "delete"
 Originally Posted by Lindley
Not entirely true. That's certainly the philosophy of C; but C++ has embraced a policy emphasizing safety from the start, and enhancements like the STL only take things further in that direction. Lots of stuff is kept "under the hood" to make your code safer.
That said, the reason why is fairly simple: The delete operator takes a pointer by value. Just like any pointer passed by value, the function can modify what it points to (in this case, an allocated memory block), but it cannot modify the pointer itself in any way visible to the caller.
Could the language have been written so that delete took the pointer by reference instead? Yeah, probably. But there were reasons why that seemed like a bad idea, I'm sure.
The safest policy is to design your code so that you never have to call delete. I'm not endorsing memory leaks; but usage of STL containers can reduce most of your need to call "new", and usage of smart pointers can remove your need to explicitly call delete even when you do call new. Together, STL containers and smart pointers will make your code infinitely easier to maintain.
Good point.
Thanks for your help.
-
January 22nd, 2010, 06:36 AM
#7
Re: question on "delete"
 Originally Posted by delpi
I learned that it safe "delete" a 0 (NULL) pointer, but it's undefined behavior to "delete" a pointer twice. So they told me to always add "p=0;" after deleting p.
The suggested DELETE macro preferably could be complemented with an assert, like
Code:
#define DELETE(ptr);\
{\
_assert(ptr); // throws if ptr is 0
delete ptr;\
ptr = 0;\
}
Now you'll get a runtime error in debug mode if ptr is 0. This allows you to fix the bug and not just hide it. Otherwise you're just pouring perfume on a turd.
Also check out shared_ptr, soon to become part of the C++ standard library. It's a reference counting smart pointer which takes on the responsibility of managing an object's life-time.
Last edited by nuzzle; January 22nd, 2010 at 06:42 AM.
-
January 22nd, 2010, 06:58 AM
#8
-
January 22nd, 2010, 07:26 AM
#9
Re: question on "delete"
 Originally Posted by delpi
Here comes my question:
It seems that we can just add "p=0" into the implementation of the "delete" operator in order to save some typing for coder and it's much safer. But so far it's not the case. So I am wondering why it's not and what's side effect of this addition.
I would guess that in a big majority of cases (probably >90%) the pointer for which delete is being called will either run out of scope shortly after the delete call, or the object it belongs do will be destroyed (delete called in destructor). Setting a variable just before it is getting deleted is useless code, so your suggestion would introduce useless code in 90% of the cases where the use would be in only 10%.
If you stick with good design and call delete only in destructor of your objects, you will hardly encounter the double-delete problem.
More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason - including blind stupidity. --W.A.Wulf
Premature optimization is the root of all evil --Donald E. Knuth
Please read Information on posting before posting, especially the info on using [code] tags.
-
January 22nd, 2010, 08:41 AM
#10
Re: question on "delete"
 Originally Posted by nuzzle
The suggested DELETE macro preferably could be complemented with an assert, like
Code:
#define DELETE(ptr);\
{\
_assert(ptr); // throws if ptr is 0
delete ptr;\
ptr = 0;\
}
Now you'll get a runtime error in debug mode if ptr is 0. This allows you to fix the bug and not just hide it. Otherwise you're just pouring perfume on a turd.
There's no point in the assert, honestly. Calling delete on a null pointer is a no-op so there's no reason to check for that, and if the pointer has already been deleted but not set back to null, the assert isn't going to catch it.
-
January 22nd, 2010, 09:12 AM
#11
Re: question on "delete"
 Originally Posted by Speedo
There's no point in the assert, honestly. Calling delete on a null pointer is a no-op so there's no reason to check for that, and if the pointer has already been deleted but not set back to null, the assert isn't going to catch it.
I've assumed that the DELETE macro is used through-out of course, not just sometimes. Then the assert will raise an exception if a pointer is deleted twice. (and even better, if all pointers are systematically initialized to null it will also raise an exception if a pointer was never assigned an object before it was deleted.)
So there's every reason in the world to add the assert. It will alarm you about a bug that would otherwise be passed over in silence. Without the assert the DELETE macro is like pouring perfume on a turd. It just removes the bad smell. But with the assert it becomes a tool in helping you to find and remove the actual turd.
Last edited by nuzzle; January 22nd, 2010 at 10:13 AM.
-
January 22nd, 2010, 09:34 AM
#12
Re: question on "delete"
 Originally Posted by delpi
It seems that we can just add "p=0" into the implementation of the "delete" operator in order to save some typing for coder and it's much safer. But so far it's not the case. So I am wondering why it's not and what's side effect of this addition.
Richard.J linked to an article where Stroustrup answers your question by answering the FAQ: Why doesn't delete zero out its operand? That same article provides an example of a destroy function template that is perhaps a better alternative to ninja9578's DELETE macro example.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|