class Widget
{
public:
Widget() {
cout<<"~Widget()"<<endl;
}
~Widget() {
cout<<"~Widget()"<<endl;
}
void* operator new(size_t sz) throw(bad_alloc) {
cout<<"operator new"<<endl;
throw bad_alloc();
}
void operator delete(void *v) {
cout<<"operator delete"<<endl;
}
};
int main()
{
Widget* w = 0;
try {
w = new Widget();
}
catch(bad_alloc) {
cout<<"Out of Memory"<<endl;
}
delete w;
getch();
return 1;
}
In this code, delete w
does not call the overloaded delete
operator when the destructor is there. If the destructor is omitted, the overloaded delete
is called. Why is this so?
Output when ~Widget() is written
operator new
Out of Memory
Output when ~Widget() is not written
operator new
Out of Memory
operator delete
Would like a leave a comment, instead of answer, didn't have enough privileges being a new member.
An exception is being raised during the creation of object. The destructor is not getting called, as the object itself is not created.
That you can also observe, as the messages from the constructor & destructor are not getting displayed.
But, the delete is being called when the destructor is not defined. If thought in the directon that when destrcutor is not defined, C++ Compiler considers it as any other operator, the compiler by default provides a destructor when not defined.
You were trying to delete a NULL pointer. So, the destructor was not getting called.
Output:
I remember something similar on operator delete a while ago in comp.lang.c++.moderated. I cannot find it now, but the answer stated something like this ..
And James Kanze specifically said:
I remember this becoz i had a similar prob sometime back and had preserved the answer in a .txt file.
UPDATE-1:
Oh i found it here. Also read this link defect report. So, the answer is Unspecified. Chapter 5.3.5/7.
I don't have a good answer, but I have simplified the issue slightly. The following code removes the operator new and exception handling:
This still exhibits the same behaviour and des so on both VC++ and g++.
Of course, deleting a NULL pointer is a no-op, so the compiler does not have to call operator delete. If one actually allocates an object:
then things work as expected.
The object destructor is called before the delete operator. So my guess would be that it tries to call the destructor, realizes that the pointer is NULL therefore
As Neil said, if w contains a Widget, it should work.
First of all, this can really be simplified down to
delete (Widget*)0
- everything else in yourmain()
is unnecessary to repro this.It's a code generation artefact that happens because 1) user-defined
operator delete
must be able to handle NULL values, and 2) compiler tries to generate the most optimal code possible.First let's consider the case when no user-defined destructor is involved. If that's the case, there's no code to run on the instance, except for
operator delete
. There's no point in checking for null before transferring control tooperator delete
, because the latter should do a check anyway; and so the compiler just generates unconditional call ofoperator delete
(and you see the latter print a message).Now the second case - destructor was defined. This means that your
delete
statement actually expands into two calls - destructor, andoperator delete
. But destructor cannot be safely called on a null pointer, because it could try to access class fields (the compiler could figure out that your particular destructor doesn't really do it and so is safe to call with nullthis
, but looks like they don't bother in practice). So it inserts a null check in there before the destructor call. And once the check is already there, it might as well use it skip the call tooperator delete
, too - after all it's required to be a no-op anyway, and it will spare an extra meaningless check for null insideoperator delete
itself in case the pointer actually is null.So far as I can see, nothing in this is in any way guaranteed by ISO C++ spec. It's just that both compilers do the same optimization here.