Why is the release function not called when the constructor object throws a new expression?

If I define the delete operator as the following, and if the constructor of the object started a new expression, I expected to see the result of the call for the specific delete operator:

#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 simply displays alloc , why is the delete statement not called? The standard [expr.new] states that:

If any part of the initialization of the object described above is completed by throwing an exception and a suitable deallocation function can be found, the release function is called freeing the memory in which the object, after which the exception continues to propagate in the context of the new expression.

+5
source share
3 answers

If you correct your code to throw exceptions, it works as expected:

 int main(int argc,char* arg[]) { try { new A(2); } catch (...) {} } 

Demo

+1
source

As already noted, this is because you will not catch the exception. As standard notes:

C ++ 11 ยง15.3 / 9 :
"If no matching handler is found, the std::terminate() function is called, regardless of whether the stack was unwound before this call to std::terminate() determined by the implementation."

Although I think this is not specifically related to the stack in your case, the same principle will be here. Thus, it really depends on the implementation if any memory is cleared. As we see here, this is usually not the case, because the operating system clears the memory anyway.

+2
source

If during construction using new constructor throws an exception, the C ++ runtime library:

  • calls std::terminate() if no matching catch handler is found. Regardless of whether delete is called, an implementation is defined.

or

  1. calls delete for you before "sending" this exception to the appropriate catch handler if it is found, although the destructor is not called - i.e. ~A() , if you have one, will not be called when i greater than 1.
+1
source

Source: https://habr.com/ru/post/1271417/


All Articles