Why is overloaded deletion not called when an exception is thrown in the destructor?

I wrote the code below, which overloads the new and delete operators and throws an exception in the destructor.

When an exception is thrown, why is the code in the delete not executed (and "printed" so far)?

If this should not be done, (how) is memory freed? Is one of the other delete ? Can overloading one of them lead to the execution of the corresponding code? Or is memory simply not freed because unsuccessful destruction implies that perhaps it should not be?

 #include <iostream> using namespace std; class A { public: A() { } ~A() noexcept(false) { throw exception(); } void* operator new (std::size_t count) { cout << "hi" << endl; return ::operator new(count); } void operator delete (void* ptr) { cout << "bye" << endl; return ::operator delete(ptr); } // using these (with corresponding new's) don't seem to work either // void operator delete (void* ptr, const std::nothrow_t& tag); // void operator delete (void* ptr, void* place); }; int main() { A* a = new A(); try { delete a; } catch(...) { cout << "eek" << endl; } return 0; } 

Output:

 hi eek 

Live demo .

I watched:

  • exception of destructor exceptions
  • How C ++ frees memory when the constructor throws an exception and uses a custom new
  • And others

But I could not find the answer to what exactly happens (1) for an exception in the destructor (unlike the constructor) and (2) with overloaded deletion.

I don’t need a lecture on eliminating bad practice from the destructor - I just came across a similar code and I am curious about the behavior.


I would prefer an answer supported by a standard or similar link, if such links exist.

+8
c ++ exception c ++ 11 destructor delete-operator
source share
3 answers

standard draft N4296 5.3.5, p. 121 says:

[expr.delete] [Note: the maladaptation function is called regardless of whether the destructor for the object or any element of the array throws an exception. - final note]

Thus, operator delete should be called unceremonious, which calls the destructor.

However, as it turned out from the comments, some compilers incorrectly call operator delete . This can be solved as an error compiler.

Bug fixed:

+5
source share

In the C ++ 1998 standard (ISO / IEC 14882 First edition, 1998-09-01), the operation of the deletion expression is quite simply outlined in "Section 5.3.5" Deleting [expr.delete] "in clauses 6 and 7.

6 The expression expression will call the destructor (if any) for the object or elements of the array to be deleted. In the case of an array, the elements will be destroyed in the decreasing order of the address (i.e., in the reverse order of completion of their constructor; see 12.6.2).

7 The expression expression will call the release function (3.7.3.2).

In combination, these sentences require that the destructor be called (or destructors for the array) and that the release function be called unconditionally. There is no provision that you do not call the release function if an exception is thrown.

In the 1998 standard, language lawyers and compiler developers are likely to enjoy sophistry to discuss a different interpretation than I said above. Fortunately, in later standards things are clearer ...

In draft N4296, available from open-std.org , the same sentences are expanded as follows: (from the memory, the wording in the official standard is the same, but I do not have a copy on my current computer)
(my accent)

6 If the operand value of the delete-expression is not a null pointer value, the expression-expression will call the destructor (if any) for the object or elements of the deleted array. In the case of an array, the elements will be destroyed in descending order of the address (i.e., in the reverse order of completion of their constructor, see 12.6.2).

7 If the value of the operand of the delete-expression is not the value of a null pointer, then:

(7.1). If the allocation call for the new expression for the object to be deleted was not omitted and the distribution was not expanded (5.3.4), delete-expression should call the release function (3.7.4.2). The value returned from the distribution invocation of the new expression is passed as the first argument to the release function.

(7.2) - Otherwise, if the distribution was expanded or was provided by expanding the allocation of another new expression and the deletion expression for any other pointer value created by the new expression that had storage, the extension provided by the new expression was evaluated, delete-expression should call the release function. The value returned from the distribution invocation of the extended new expression is passed as the first argument to the release function.

(7.3) - Otherwise, the expression delete will not call the release function (3.7.4.2).

Otherwise, it is not indicated whether the release function will be called. [Note: The release function is called regardless of whether the destructor for the object or any element of the array throws an exception. - end of note]

The note at the end said that the release function should be called even if the destructor throws an exception.

I'm not sure which evolution of the standard was originally written, but based on the foregoing, the items will probably remain in section 5.3.5 (tag [expr.delete]).

+2
source share

The destructor is called before calling the delete operator. See cppreference - delete expression

If the expression is not a null pointer, the delete expression calls the destructor (if any) for the object to be destroyed or for each array to be destroyed (starting from the last element in the first element of the array). After that, if the corresponding new expression will not be combined with another new expression (since C ++ 14), the delete expression calls the release function, either the delete operator (for the first version of the expression) or the delete [] operator (for the second version of the expression).

Because of this order of operations, the destructor is called and throws an exception before you call your overloaded version of the delete statement.

-one
source share

All Articles