Balog said:
"Kai-Uwe Bux" <
[email protected]>
Probably we can agree that the difference-set is restricted to the
"unused" pointers that are members of living objects and a few-lines area
for locals.
I keep that population to minimum, and see no reason why having all those
few pointers set to NULL would hurt. Just like I don't keep spolled food
around the house.
If it disappears, then there is no need to nulling. (however optimizers
probably remove the assignment anyway, just as in the sases when you set a
different value to the pointer a few lines after... back with C we used
macros that did free and set null almost exclusively without observing
peroformance problems.)
IMO there is a fair (even if not perfect) rationale to setting an invalid
pointer to NULL, and would be interested in the rationale of not setting
it. Honestly it sounds like 'ignore the seat belts, as they won't detect a
bomb attached to your ignition'.
[...]
The question has two aspects, at the very least: (a) should nulling pointers
upon deletion be part of an overall strategy to ensure resource correctness
of the program? and (b) could nulling pointers be added on top of any other
strategy without harm?
As for (a), my experience is that RAII and deliberate use of smart pointers
(of various flavors) renders nulling pointers superfluous and still ensures
that all non-null pointers are valid. As a by-product, a null value of a
pointer usually has a more specific meaning (e.g., indicating the leaf of a
data structure).
Most raw pointers are indeed used for navigation around the data and
so 0 is the edge of navigation. Smart pointers are often too dumb for
such cases. Other usage of raw pointers is performance optimization
where smart pointer was too slow. Rest of the raw pointer usages might
be well considered as premature optimization.
Lets take for smart pointer example the shared_ptr. Instead of
deleteing its pointee people may reset() the pointer at some spot.
After then it is NULL. If they reset() it later again, then yes,
valgrind does detect nothing there too. Lets say developers have to
refactor it into raw pointer there instead of shared_ptr because of
performance. Setting it to NULL after deleting makes raw pointer not
perfect but at least it behaves a tiny bit like shared_ptr.
It is sad that interface of some smart pointers causes too lot of
noise in code. Setting a raw pointer to NULL is clean and tidy code if
to compare with serious weak_ptr usage.
Now for (b), I don't think it's always a harmless addition. Of course, if
the code is correct, it will stay correct. However we have to think of bugs.
In my code, a double deletion is almost certainly indicative of a deeper
problem (saying that I lost track of which pointees exist).
Is the existence of pointees a meta-information? Do you keep track of
the pointees by using something else, not by using pointer values that
point at them? If this is meta information then i am not sure how well
it scales.
I prefer seeing
valgrind spot that double deletion to the double deletion turning into a
silent null-op.
This sounds like some sort of "single new single delete" idiom used,
so multiple places of deletion are design bugs. I do not follow any
such SESE-like idioms. Most important objects keep more valuable
resources than the memory in what they locate (like files, hardware
ports, operating system handles) and destruction as soon as it is
clear they are not needed anymore is often a good idea. Everybody love
that "resource acquisition is initialization" thingy. Why some
seemingly hate its "resource releasing is uninitialization"
brother?
(Being a little paranoid, I have seriously considered creating a smart
pointer just for debugging. It would detect double deletion, dereferencing
invalid pointers, and using pointers polymorphically with classes that lack
virtual destructors.)
Double deletion happens to me when these are different pointers to
same object so nulling one does not invalidate other. Dereferencing
invalid pointers happens rarely to me too, but i can not say same
about my team members. Detecting delete polymorphic pointer to class
without virtual destructor there are some static analysis tools.
Btw ... polymorphic shared_ptr actually calls correct destructor
itself if most derived object pointer was passed to it when
constructing. Protected non-virtual destructors work better with
shared_ptr. This might also be bad and hide some design flaw from you?