Topic: Checking for nullness in operator delete
Author: smeyers@aristeia.com (Scott Meyers)
Date: 1999/04/18 Raw View
> Read it again more carefully. The "missing space" isn't a typo--
> Siemel Naran created a function named operatordelete().
You and Siemel are right, I'm wrong. Sorry. Sigh. I can't say I endorse
the style, but the mistake was mine, not his.
Scott
--
Scott Meyers, Ph.D. smeyers@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: smeyers@aristeia.com (Scott Meyers)
Date: 1999/04/15 Raw View
On 15 Apr 99 12:28:30 GMT, Siemel Naran wrote:
> // MyClass.h
> namespace myspace {
> class MyClass {
> public:
> static void operator delete(void *, size_t);
> ...
> };
> }
>
> // MyClass.c
> #include "MyClass.h"
> void myspace::operator delete(void * ptr, size_t size) {
You mean myspace::MyClass::operator delete. Note that operators new and
delete may not be declared at namespace scope. (At least I thought they
couldn't be, but now I can't find the restriction in the standard. It is
still there, isn't it?)
> Change this to:
>
> // MyClass.h
> namespace myspace {
> class MyClass {
> private:
> static void operatordelete(void *, size_t);
> public:
> static void operator delete(void * ptr, size_t size) {
> if (!ptr) return;
> operatordelete(ptr,size);
Do you really want infinite recursion here? If you meant to call
::operator delete, note that you can't generally call ::operator
delete(ptr, size), because there is no two-argument version of ::operator
delete by default.
Also note that in this design, the one-argument version of operator delete
becomes the "normal" version, so this actually changes the semantics of the
class.
> Steve said that it is possible to call ::operator delete explicitly.
> Indeed, we use this call to free memory in our allocators. But how
> often does one call MyClass::operator delete explicitly? So my
> question: is it necessary for a class operator delete to check for
> null?
It's necessary to be compliant with the specified interface for operator
delete. See 18.4.1.1 para 12.
Scott
--
Scott Meyers, Ph.D. smeyers@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/04/16 Raw View
On 15 Apr 99 14:18:37 GMT, Scott Meyers <smeyers@aristeia.com> wrote:
>On 15 Apr 99 12:28:30 GMT, Siemel Naran wrote:
>> Change this to:
>>
>> // MyClass.h
>> namespace myspace {
>> class MyClass {
>> private:
>> static void operatordelete(void *, size_t);
>> public:
>> static void operator delete(void * ptr, size_t size) {
>> if (!ptr) return;
>> operatordelete(ptr,size);
>
>Do you really want infinite recursion here? If you meant to call
>::operator delete, note that you can't generally call ::operator
>delete(ptr, size), because there is no two-argument version of ::operator
>delete by default.
What infinite version are you talking about?
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "AllanW {formerly AllanW@my-dejanews.com}" <allan_w@my-dejanews.com>
Date: 1999/04/16 Raw View
In article <MPG.117f9226e16198919896a1@news.teleport.com>,
smeyers@aristeia.com (Scott Meyers) wrote:
> On 15 Apr 99 12:28:30 GMT, Siemel Naran wrote:
> > Change this to:
> >
> > // MyClass.h
> > namespace myspace {
> > class MyClass {
> > private:
> > static void operatordelete(void *, size_t);
> > public:
> > static void operator delete(void * ptr, size_t size) {
> > if (!ptr) return;
> > operatordelete(ptr,size);
>
> Do you really want infinite recursion here? If you meant to call
Read it again more carefully. The "missing space" isn't a typo--
Siemel Naran created a function named operatordelete().
----
Allan_W@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "AllanW {formerly AllanW@my-dejanews.com}" <allan_w@my-dejanews.com>
Date: 1999/04/16 Raw View
> In article <3712E9D5.CCC88792@sea.ericsson.se>,
> Gerhard Menzl <gerhard.menzl@sea.ericsson.se> wrote:
> >the - admittedly exotic -
> >possibility of an explicit call to operator delete requires the
> >redundant test for nullness.
In article <_3KQ2.530$kM2.51553@burlma1-snr2>,
Barry Margolin <barmar@bbnplanet.com> wrote:
> Since it's such an "exotic" thing to do, perhaps the onus should be put on
> the author of the code that contains the explicit call.
I think that the rationale for this is left over from C's malloc/free.
In any case, the check for null is such a small fraction of the overall
work that delete() will do, the "extra" check can hardly matter much.
----
Allan_W@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: smeyers@aristeia.com (Scott Meyers)
Date: 1999/04/13 Raw View
Section 18.4.1 of the standard makes clear that operator delete and
operator delete[] must be able to cope with a null pointer being passed to
them. I'm trying to figure out why this requirement exists.
Consider the general case of a delete expression involving a pointer to a
user-defined type with a nontrivial destructor:
Widget *pw = new Widget;
...
delete pw;
It seems to me that the generated code has to test pw for nullness, because
it won't want to invoke a Widget destructor on a null pointer. That is,
the generated code has to look something like this:
if (pw != NULL) {
pw->~Widget();
operator delete(pw);
}
(This ignores the possibility of a class-specific operator delete, but the
idea is the same.) My point is that since the code above has to check pw
for nullness, there's no point in operator delete doing it, too.
For built-in types and types with trivial destructors, the argument above
fails to hold, but it still seems that the "right" place to test for
nullness is inside the code the compiler generates for the delete
expression, not inside operator delete. In fact, it seems to me that the
current specification pretty much guarantees at least two checks for
nullness is some cases. Am I missing something?
Scott
--
Scott Meyers, Ph.D. smeyers@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Gerhard Menzl <gerhard.menzl@sea.ericsson.se>
Date: 1999/04/13 Raw View
Scott Meyers wrote:
> Section 18.4.1 of the standard makes clear that operator delete and
> operator delete[] must be able to cope with a null pointer being
> passed to them. I'm trying to figure out why this requirement
> exists.
> Consider the general case of a delete expression involving a pointer
> to a user-defined type with a nontrivial destructor:
> Widget *pw = new Widget;
> ...
> delete pw;
> It seems to me that the generated code has to test pw for nullness,
> because it won't want to invoke a Widget destructor on a null
> pointer. That is,the generated code has to look something like this:
> if (pw != NULL) {
> pw->~Widget();
> operator delete(pw);
> }
> (This ignores the possibility of a class-specific operator delete,
> but the idea is the same.) My point is that since the code above has
> to check pw for nullness, there's no point in operator delete doing
> it, too.
> For built-in types and types with trivial destructors, the argument
> above fails to hold, but it still seems that the "right" place to
> test for nullness is inside the code the compiler generates for the
> delete expression, not inside operator delete. In fact, it seems to
> me that the current specification pretty much guarantees at least two
> checks for nullness is some cases. Am I missing something?
I recently asked the same question in comp.lang.c++.moderated. I think
it was Steve Clamage who pointed out that the - admittedly exotic -
possibility of an explicit call to operator delete requires the
redundant test for nullness.
Gerhard Menzl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/04/15 Raw View
On 14 Apr 99 05:21:43 GMT, Scott Meyers <smeyers@aristeia.com> wrote:
>1. Safer? Only if everybody who writes operator delete remembers to check
> for null. What's more likely: that the writer of a compiler will
> remember or that every user who codes an operator delete will remember?
It's more likely for the compiler writer to remember, rather than the
author of MyClass::operator delete. So your point accepted.
>2. Negligable in time? That depends quite a lot of how memory is freed.
> For pool-based allocators, it's not clear to me that it's truly
> negligable.
The optimization that I mentioned can already be done for inline
functions. So if you have:
// MyClass.h
namespace myspace {
class MyClass {
public:
static void operator delete(void *, size_t);
...
};
}
// MyClass.c
#include "MyClass.h"
void myspace::operator delete(void * ptr, size_t size) {
if (!ptr) return;
/*stuff*/
}
...
Change this to:
// MyClass.h
namespace myspace {
class MyClass {
private:
static void operatordelete(void *, size_t);
public:
static void operator delete(void * ptr, size_t size) {
if (!ptr) return;
operatordelete(ptr,size);
}
...
};
}
// MyClass.c
#include "MyClass.h"
void myspace::operatordelete(void * ptr, size_t size) {
// can assume 'ptr' is non-null
/*stuff*/
}
...
So in client code
delete w;
may becomes
if (w) { w->~Widget(); Widget::operator delete(w,w.sizeof()); }
A good compiler should optimize this to:
if (w) { w->~Widget(); Widget::operatordelete(w,w.sizeof()); }
I believe KCC does this optimization.
> In other words,
>it's foolish to *expect* compilers to do fancy things.
The optimization I mentioned is fancy especially because it works on
non-inline functions. (If the function is inline, compilers can
already do the optimization.) So I don't expect compilers to do it
in the near future.
>I agree with Barry Margolin that it would be better to put the onus of
>checking for nullness on the caller of operator delete, but I also have
>sympathy for the desire to remain interface-compatible with free. At any
>rate, the standard says what the standard says, and I feel that I now have
>a better understanding for why it reads as it does.
Steve said that it is possible to call ::operator delete explicitly.
Indeed, we use this call to free memory in our allocators. But how
often does one call MyClass::operator delete explicitly? So my
question: is it necessary for a class operator delete to check for
null?
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Barry Margolin <barmar@bbnplanet.com>
Date: 1999/04/13 Raw View
In article <3712E9D5.CCC88792@sea.ericsson.se>,
Gerhard Menzl <gerhard.menzl@sea.ericsson.se> wrote:
>I recently asked the same question in comp.lang.c++.moderated. I think
>it was Steve Clamage who pointed out that the - admittedly exotic -
>possibility of an explicit call to operator delete requires the
>redundant test for nullness.
Since it's such an "exotic" thing to do, perhaps the onus should be put on
the author of the code that contains the explicit call.
--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/04/13 Raw View
smeyers@aristeia.com (Scott Meyers) writes:
>Section 18.4.1 of the standard makes clear that operator delete and
>operator delete[] must be able to cope with a null pointer being passed to
>them. I'm trying to figure out why this requirement exists. ...
> Widget *pw = new Widget;
> ...
> delete pw;
>It seems to me that the generated code has to test pw for nullness, because
>it won't want to invoke a Widget destructor on a null pointer. ...
> My point is that since the code above has to check pw
>for nullness, there's no point in operator delete doing it, too.
But you can call operator delete directly, and sometimes you
want to do so.
Just as free() is required to do nothing when called with a null
pointer, so is operator delete.
--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/04/13 Raw View
On 13 Apr 99 06:54:25 GMT, Gerhard Menzl <gerhard.menzl@sea.ericsson.se> wrote:
>I recently asked the same question in comp.lang.c++.moderated. I think
>it was Steve Clamage who pointed out that the - admittedly exotic -
>possibility of an explicit call to operator delete requires the
>redundant test for nullness.
Besides, what if ::operator delete(p) just forwards to std::free(p).
We all know that std::free(void * ptr) has to check 'ptr' against
null.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James.Kanze@dresdner-bank.com
Date: 1999/04/13 Raw View
In article <3712E9D5.CCC88792@sea.ericsson.se>,
Gerhard Menzl <gerhard.menzl@sea.ericsson.se> wrote:
> Scott Meyers wrote:
>
> > Section 18.4.1 of the standard makes clear that operator delete and
> > operator delete[] must be able to cope with a null pointer being
> > passed to them. I'm trying to figure out why this requirement
> > exists.
>
> > Consider the general case of a delete expression involving a pointer
> > to a user-defined type with a nontrivial destructor:
>
> > Widget *pw = new Widget;
> > ...
> > delete pw;
>
> > It seems to me that the generated code has to test pw for nullness,
> > because it won't want to invoke a Widget destructor on a null
> > pointer. That is,the generated code has to look something like this:
>
> > if (pw != NULL) {
> > pw->~Widget();
> > operator delete(pw);
> > }
>
> > (This ignores the possibility of a class-specific operator delete,
> > but the idea is the same.) My point is that since the code above has
> > to check pw for nullness, there's no point in operator delete doing
> > it, too.
>
> > For built-in types and types with trivial destructors, the argument
> > above fails to hold, but it still seems that the "right" place to
> > test for nullness is inside the code the compiler generates for the
> > delete expression, not inside operator delete. In fact, it seems to
> > me that the current specification pretty much guarantees at least two
> > checks for nullness is some cases. Am I missing something?
>
> I recently asked the same question in comp.lang.c++.moderated. I think
> it was Steve Clamage who pointed out that the - admittedly exotic -
> possibility of an explicit call to operator delete requires the
> redundant test for nullness.
So.
I tend to agree with Scott on this one, for another reason: if you write
a user defined operator delete, *you* have to test for nullness. When
all is said and done, it is one more error for you to make. Acceptable,
perhaps, if the alternative had great cost. But as Scott points out,
for once, the safe solution is actually cheaper in runtime, or no more
expensive in the worst case.
--
James Kanze mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient e objet/
Beratung in objekt orientierter Datenverarbeitung
Ziegelh ttenweg 17a, 60598 Frankfurt, Germany Tel. +49 (069) 63 19 86 27
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/04/13 Raw View
On 13 Apr 99 05:43:24 GMT, Scott Meyers <smeyers@aristeia.com> wrote:
>For built-in types and types with trivial destructors, the argument above
>fails to hold, but it still seems that the "right" place to test for
>nullness is inside the code the compiler generates for the delete
>expression, not inside operator delete. In fact, it seems to me that the
>current specification pretty much guarantees at least two checks for
>nullness is some cases. Am I missing something?
The practice of checking against null twice stems from a safer style of
programming. Note: the extra time spent in the second check of 'ptr'
against null is negligible compared to the time spent in the complex
details of freeing up the memory.
I've mentioned the following optimization before on
comp.lang.c++.moderated. Given a function definition like
void F(void * ptr) { if (!ptr) return; ... }
the compiler can generate two functions f.
void F(void * ptr) { if (!ptr) return; _f(ptr) } // as above
/*inline*/ void _F(void * ptr) { ... } // assumes 'ptr' non-null
Hence, given client code
Widget * w=new Widget();
delete w;
which transforms to
Widget * w=new Widget();
if (w) { w->~Widget(); ::operator delete(w); }
which in view of the argument above with F==operator delete, becomes
Widget * w=new Widget();
if (w) { w->~Widget(); ::_operator delete(w); }
where ::_operator delete(void * ptr) assumes that 'ptr' is non-null.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: smeyers@aristeia.com (Scott Meyers)
Date: 1999/04/14 Raw View
On 13 Apr 99 17:31:28 GMT, Siemel Naran wrote:
> The practice of checking against null twice stems from a safer style of
> programming. Note: the extra time spent in the second check of 'ptr'
> against null is negligible compared to the time spent in the complex
> details of freeing up the memory.
1. Safer? Only if everybody who writes operator delete remembers to check
for null. What's more likely: that the writer of a compiler will
remember or that every user who codes an operator delete will remember?
2. Negligable in time? That depends quite a lot of how memory is freed.
For pool-based allocators, it's not clear to me that it's truly
negligable.
> I've mentioned the following optimization before on
> comp.lang.c++.moderated. Given a function definition like
> void F(void * ptr) { if (!ptr) return; ... }
> the compiler can generate two functions f.
> void F(void * ptr) { if (!ptr) return; _f(ptr) } // as above
> /*inline*/ void _F(void * ptr) { ... } // assumes 'ptr' non-null
Yes, compilers can do this, but it would be foolish to define a provision
of the standard on the assumption that compilers will do this. As noted in
another thread, several common compilers don't even understand that private
types are inaccessible outside the class defining them. In other words,
it's foolish to *expect* compilers to do fancy things. (No, this doesn't
contradict my argument (1) above. Once the bug is fixed, all users get the
fix automatically.)
I agree with Barry Margolin that it would be better to put the onus of
checking for nullness on the caller of operator delete, but I also have
sympathy for the desire to remain interface-compatible with free. At any
rate, the standard says what the standard says, and I feel that I now have
a better understanding for why it reads as it does.
Not that I like it any better :-)
Scott
--
Scott Meyers, Ph.D. smeyers@aristeia.com
Software Development Consultant http://www.aristeia.com/
Visit http://meyerscd.awl.com/ to demo the Effective C++ CD
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]