Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why deallocation function is not called when object constructor throw in a new expression?

Tags:

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.

like image 865
Oliv Avatar asked Sep 01 '17 08:09

Oliv


2 Answers

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 function std::terminate() is called; whether or not the stack is unwound before this call to std::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.

like image 64
koalo Avatar answered Oct 01 '22 05:10

koalo


If you fix your code to throw exception, it works as expected:

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

Demo

like image 29
Jarod42 Avatar answered Oct 01 '22 05:10

Jarod42