I've written the below code which overloads the new
and delete
operators and throws an exception in the destructor.
When the exception is thrown, why is the code in the delete
operator not executed (and "bye" printed)?
If it shouldn't be executed, (how) is the memory freed? Is one of the other delete
operators called? Would overloading one of them instead result in the corresponding code being executed? Or is the memory simply not freed because a failed destruction implies that maybe it shouldn't 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
I looked at:
- throwing exceptions out of a destructor
- How does C++ free the memory when a constructor throws an exception and a custom new is used
- And others
But I couldn't find an answer to what exactly happens (1) for an exception in the destructor (as opposed to the constructor) and (2) with an overloaded delete.
I don't need a lecture on throwing an exception in a destructor being bad practice - I just ran into similar code and I'm curious about the behaviour.
I would prefer an answer supported by the standard or similar references, if such references exist.
delete
be called if you've thrown an exception in the destructor ofA
? The purpose ofdelete
would be to, for example, deallocate resources. Would you want your resources deallocated before~A()
is executed? It would make sense that~A()
executes, and the logic for yourdelete
gets called afterwards. Having said that, letting exceptions escape out of a destructor is not a good idea. – Meekdelete
should be called because there isn't much the compiler can do about the destructor failing. Even if all applicable resources aren't freed, letting more memory leak doesn't seem like the best way to handle that. There is a logical argument behind trying to destruct the object again later, but successful destruction may not be possible and that conflicts with the other compilers' behaviour described here and Biagio's answer. – Nutt