If I define operator delete as following and if an object constructor throw in the new expression I expected to see the result of the call to the defined operator delete:
#include <new>
#include <cstdlib>
#include <iostream>
void*
operator new(std::size_t s){
std::cout << "alloc " << std::endl;
return std::malloc(s);
}
void
operator delete(void* p) noexcept {
std::cout << "dealloc " << std::endl;
std::free(p);
}
void
operator delete(void* p,std::size_t) noexcept{
std::free(p);
std::cout << "dealloc s" << std::endl;
}
struct A{
A(int i){
if(i>0)
throw 10;
}
};
int main(int argc// will equal 10
,char* arg[])
{
for(int i=0;i<argc;++i)
auto p=new A{argc};
return 0;
}
This program just output alloc
, why the operator delete are not called? In the standard [expr.new] it is specified that:
If any part of the object initialization described above terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression.
As others already noted, it is because you do not catch the exception. As the standard notes:
C++11 §15.3/9:
“If no matching handler is found, the functionstd::terminate()
is called; whether or not the stack is unwound before this call tostd::terminate()
is implementation-defined.”
While I think this is not specifically related to the stack in your case, the same principle will hold here, too. So it is actually up to the implementation if any memory is cleaned up. As we see here, it is usually not the case, because the operating system cleans up the memory anyway.
If you fix your code to throw exception, it works as expected:
int main(int argc,char* arg[])
{
try {
new A(2);
}
catch (...)
{}
}
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With