Thanks
Allan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
As far as the FAQ is concerned, I don't recall an argument against
setting pointer to null after delete.
If the pointer's lifetime isn't ending, I would say setting it to null
is often useful. For instance, if in your code there are some things
you want to do when there is an object being pointed to and some
different things when there is no object, setting it to null is an
easy way to tell if there is an object or not.
If the pointer's lifetime is about up, for instance a class member
variable in the class's destructor, then it is less useful to set it
to null.
Also, some upcoming versions of C++ are going to have a nullptr
keyword which you can use instead of NULL.
Yes, there is.
The popular legend about setting a pointer to null after `delete` is
that is will allegedly make you safe you from the double-delete problem
(i.e. when the same pointer value is passed to `delete` more than once).
In reality, the _real_ double-delete problem occurs most of the time
when the same memory block is `delete`d multiple times through two or
more _different_ pointer objects holding the same address. Needless to
say, setting a pointer to null after `delete` will achieve absolutely
nothing to prevent the problem.
While it is true that setting a pointer to null after `delete` might
save you from double-delete through the same pointer, in reality in 9
cases out of 10 such a situation indicates a more generic problem with
the overall logic of the code. Treating it as a mere double-delete in
general case will only threat a symptom of the problem, not the problem
itself, i.e. it will just sweep the issue under the carpet.
--
Best regards,
Andrey Tarasevich
>> Is there
>> such an arguement or did I imagine the whole thing?
> Yes, there is.
> While it is true that setting a pointer to null after `delete` might
> save you from double-delete through the same pointer, in reality in 9
> cases out of 10 such a situation indicates a more generic problem with
> the overall logic of the code. Treating it as a mere double-delete in
> general case will only threat a symptom of the problem, not the problem
> itself, i.e. it will just sweep the issue under the carpet.
Are you presenting an argument against NULLing a pointer after delete,
meaning doing so is completely useless, or simply saying that it's not
a cure-all? You seem to claim (by "Yes, there is") that you present
such an argument, but after reading it i still feel it's a good idea
to null one's pointers, but that other precautions (such as using a
smart pointer?) should be considered.
Would you mind clarifying?
--
I agree. When you encounter a double-delete problem that you didn't
expect, the correct solution is not to make the double-delete innocuous
by setting the pointer to null (which won't work in many cases as
mentioned above, or which will just hide the problem at best), but
to find out why it is happening even though it is not intended, and
to fix it so that it won't happen again.
--
Seungbeom Kim
There are of course double deletes that you DO expect. I used to
subscribe to the "NULLing is a waste of time" rule, but have noticed
several occurrences of a pattern where an object is sometimes lazily
created using new and sometimes not. The object is also often deleted
before the end of the lifetime of a containing class instance. This
tends to happen for large, expensive objects. Simplified, such a class
looks like this:
struct A {
A() : ptr(0) {}
~A() { delete ptr; }
void foo() {
if ( something ) {
ptr = new X;
...
delete ptr;
ptr = NULL;
}
}
// other stuff
X * ptr;
};
Here, it makes sense (IMHO) to NULL the pointer after deleting it, in
order to avoid special case code in the destructor. So I'd modify the
"no NULLing" rule to add an exception for member variables.
Of course, using a smart pointer might be an even better approach, but
that is a slightly different issue.
Neil Butterworth
--
In addition, these days we generally avoid manually deleting and leave
it to an encapsulating object (smart pointer, container etc.) to handle
destruction.
--
The argument agains NULLing is that it hardly ever helps.
The question is: Why do you delete the object and still keep the
pointer around? A pointer is cheap to create, so you don't have to
resuse it. Just let it go out of scope right after the delete.
Bo Persson
> struct A {
> A() : ptr(0) {}
> ~A() { delete ptr; }
> void foo() {
> if ( something ) {
> ptr = new X;
> ...
> delete ptr;
> ptr = NULL;
> }
> }
> // other stuff
> X * ptr;
> };
Which is why the recommendation is to use a smart pointer instead.
That struct as written as two double delete bugs in it, caused by the
compiler generated copy constructor and assignment operator, which do
the wrong thing. It also has a memory leak if ptr already points to an
object when A::foo is called.
I would rewrite it using either std::auto_ptr, tr1::unique_ptr, or
boost::scoped_ptr, as in:
struct A
{
void foo() {
if ( something ) {
ptr.reset(new X);
...
}
}
// other stuff
boost::scoped_ptr<X> ptr;
};
This code is both (a) simpler and (b) correct.
Unless you are writing a smart pointer or a pointer owning collection
class (and the need for the latter should mostly go away with
unique_ptr), you should never be calling delete explicitly; code which
does so is just too error prone.
> Here, it makes sense (IMHO) to NULL the pointer after deleting it, in
> order to avoid special case code in the destructor.
And if you use a smart pointer, you don't even need to write a
destructor. It just works.
> So I'd modify the
> "no NULLing" rule to add an exception for member variables.
>
> Of course, using a smart pointer might be an even better approach, but
> that is a slightly different issue.
Why is it a different issue? It's the correct solution to this problem
in all but a handful of cases.
--
Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> 773 961-1620
> Are you presenting an argument against NULLing a pointer after delete,
> meaning doing so is completely useless, or simply saying that it's not
> a cure-all?
The recommendation is to use a smart pointer class instead of explicitly
calling delete. The problem is moot at that point.
--
Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> 773 961-1620
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
Expected and designed double-deletes are fine, of course.
> I used to
> subscribe to the "NULLing is a waste of time" rule, but have noticed
> several occurrences of a pattern where an object is sometimes lazily
> created using new and sometimes not. The object is also often deleted
> before the end of the lifetime of a containing class instance.
Sure, that is an important use case of pointers -- manual control of
the lifetime. If the lifetime is deterministic, you can just declare
a variable of that object type without any pointer involved.
> Here, it makes sense (IMHO) to NULL the pointer after deleting it, in
> order to avoid special case code in the destructor. So I'd modify the
> "no NULLing" rule to add an exception for member variables.
It's most common for member variables, but it doesn't happen necessarily
for member variables; it could happen also inside a function.
I would neither call "no NULLing" a "rule", nor make an "exception"
about it, because that would make things too rigid. Do whatever you
need in the most efficient form, but not more than what's needed; if
you want to examine the pointer later, setting it to NULL can be useful.
> Of course, using a smart pointer might be an even better approach, but
> that is a slightly different issue.
Of course. In fact, using a smart pointer makes the OP's question
rather irrelevant, because the smart pointer manages its internals
by itself and you don't have a choice about NULLing.
--
Seungbeom Kim
Well, sure: NULL is often used to indicate "no resource", and that's
fine if it's been designed into the program's logic. When it comes in
through the back door as an attempt to work around a logic error, it's
treating a symptom and not the cause.
--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)