c++exception

Can an object with a throwing destructor escape a "..." matcher?


According to cppreference

The catch (...) handler matches exceptions of any type. [...] This handler may be used to ensure that no uncaught exceptions can possibly escape from a function that offers nothrow exception guarantee.

However, given the following program:

struct throwing_dtor_t {
  ~throwing_dtor_t() noexcept(false) { throw 123; }
};

int main() {
  try {
    try {
      throw throwing_dtor_t{};
    } catch (...) {
    }
  } catch (int i) {
    return i;
  }
  return 0;
}

Returns 123. Hence we can see that an exception has escaped the (...) handler.

Does this program has undefined behavior ? (I couldn't see anything in the standard saying so)


Solution

  • The thrown exception does match the catcher. What happens is that another exception is thrown as the object is destructed from the catch block after being caught. You can more easily see the same by changing the code to this:

    struct throwing_dtor_t {
      ~throwing_dtor_t() noexcept(false) { throw 123; }
    };
    
    int main(){
        try{
            try{
                throw throwing_dtor_t{};
            }
            catch(const throwing_dtor_t&){
                std::cout<<"caught throwing_dtor_t" << std::endl;
            }
        }
        catch(int i){
            std::cout<<i<<std::endl;
        }
    }
    

    So what your code is doing is something very similar to:

    int main(){
        try{
            try{
                throw 1;
            }
            catch(...){
                throw 2;
            }
        }
        catch(int i){
            std::cout<<i<<std::endl;
        }
    }
    

    So of course the outer catch will get the rethrown exception