Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Missing destructor in Visual Studio?

I wrote the following program:

// Example program
#include <iostream>
#include <string>
#include <exception>

struct A {
    A() {
        std::cout << "A ctor" << std::endl;

    }

    ~A() { 
        std::cout << "A dtor" << std::endl;
        try {
            throw std::exception();
        } catch (std::exception &e) {
            std::cout << "Internal exception caught" << std::endl;
        }
    }
};

int main()
{
    try {
        A a;
        throw std::exception();
    } catch (std::exception &e) {
        std::cout << "External exception caught" << std::endl;
    }
}

The output I expected was:

A ctor
A dtor
Internal exception caught
External exception caught

And this is what I'm getting in GCC. But when I'm using Visual Studio (version 2013) the output I'm getting is:

A ctor
External exception caught

What's going on here?

like image 540
nitzanms Avatar asked Jul 10 '17 11:07

nitzanms


1 Answers

MSVC2013 is wrong here and GCC is right. Unfortunately, I cannot find an appropriate reference from the standard now, but according to std::uncaught_exception:

For example, if stack unwinding causes a stack-allocated object to be destructed, the destructor for that object could run code that throws an exception as long as the exception is caught by some catch block before escaping the destructor.

For more details see also "Throwing during stack unwinding" section here.

Finally, as it is mentioned by @StoryTeller, this behaviour is not reproducible with newer MSVC versions.


The closest match in the standard I am able to find is the next (from the N3936 draft):

15.1 Throwing an exception [except.throw]

  1. If the exception handling mechanism, after completing the initialization of the exception object but before the activation of a handler for the exception, calls a function that exits via an exception, std::terminate is called.

So, formally, it is perfectly valid to call a function during stack unwinding process (including destructor) which might deal with exception, but if the exception inside such function is not caught by appropriate catch block then std::terminate must be called.

like image 111
Edgar Rokjān Avatar answered Oct 12 '22 21:10

Edgar Rokjān