views:

250

answers:

2

While reading answers to this question I noticed that answers (this for example) imply that operator delete can be called even when delete statement is executed on a null pointer.

So I wrote a small snippet:

class Test {
public:
    void* operator new( size_t ) { /*doesn't matter*/ return 0; }
    void operator delete( void* ptr ) {
        ptr; //to suppress warning and have a line to put breakpoint on
    }
};

int main()
{
    Test* ptr = 0;
    delete ptr;
}

and - surprisingly for me - Test::operator delete() is invoked with ptr holding a null pointer.

As I understand it operator new allocates memory and operator delete returns memory to the allocator. If I call delete statement on a null pointer it means there was no object behind the pointer and there's no memory to return to the allocator.

delete statement includes invoking a destructor. When I pass a null pointer the destructor is surely not invoked - C++ takes care of that. Then why is operator delete invoked in this case?

+11  A: 

Operator delete is just like any other operator, why wouldn't it be invoked? It can't examine its arguments before being invoked.

This is like asking why operator+ is invoked when you're adding 0.

Tyler McHenry
The `delete` statement doesn't just call `operator delete`, it first calls the destructor, and a null check is necessarily done before calling the destructor (and hence before calling `operator delete`). `operator delete` is not like other operator overloads.
Ben Voigt
Okay, but there's no way for the compiler to be sure that a user-defined operator delete is a no-op when given a null pointer. It could, for example, log something indicating that you attempted to delete a null pointer.
Tyler McHenry
Agree with Ben Voigt: when you type `delete p;`, the compiler first calls the destructor of the object and then the deallocation function `operator delete`. The system must be able to diagnose that the pointer is 0 as to avoid calling the destructor (which it won't call), so technically it could also avoid calling the deallocator.
David Rodríguez - dribeas
Actually, the C++ standard explicitly allows the compiler to avoid calling `operator delete` with a null pointer value.
Ben Voigt
+14  A: 

The language in the upcoming C++0x standard (section 5.3.5 [expr.delete]) is as follows:

If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will call a deallocation function (3.7.4.2). Otherwise, it is unspecified whether the deallocation function will be called. [ Note: The deallocation function is called regardless of whether the destructor for the object or some element of the array throws an exception. — end note ]

So it is unspecified behavior, some compilers may call operator delete when a NULL pointer is deleted and others may not.

EDIT: The term deallocation function used by the standard seems to be causing some confusion. It comes with a reference. Some key language from 3.7.4.2 [basic.stc.dynamic.deallocation] which may help clarify:

If a class T has a member deallocation function named operator delete with exactly one parameter, then that function is a usual (non-placement) deallocation function.

The standard is also very clear that user-defined operator delete needs to accept a parameter which is a null pointer value:

The value of the first argument supplied to a deallocation function may be a null pointer value; if so, and if the deallocation function is one supplied in the standard library, the call has no effect.

But because of the unspecified behavior 5.3.5, you shouldn't rely on your operator delete being called when the pointer is null.

Ben Voigt
Hmm, this snippet is talking about the deallocation function, not the operator.
Hans Passant
C++03 seems to be vague on the issue. It says "if the value of the operand of delete is the null pointer the operationhas no effect", then, "If the delete-expression callsthe implementation deallocation function...", then, "The delete-expression will call a deallocation function". So either it must not call the overloaded operator, or it's unspecified, or it must call it. One of the three ;-)
Steve Jessop
@Hans: deallocation function is the function implementing `operator delete`. This terminology comes from the fact that operators appear in expressions, while function that implement them *are* function. In other words you need to separate somehow your terminology.
ybungalobill