Visual Studio 中缺少析构函数?

Missing destructor in Visual Studio?

我写了下面的程序:

// 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;
    }
}

我预期的输出是:

A ctor
A dtor
Internal exception caught
External exception caught

这就是我在 GCC 中得到的。但是当我使用 Visual Studio(2013 版)时,我得到的输出是:

A ctor
External exception caught

这是怎么回事?

MSVC2013这里是错的,GCC是对的。不幸的是,我现在无法从标准中找到合适的参考,但根据 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.

有关更多详细信息,另请参阅 “堆栈展开期间抛出” 部分 here

最后,正如@StoryTeller 所提到的,此行为无法在较新的 MSVC 版本中重现。


我能找到的标准中最接近的匹配项是下一个(来自 N3936 草案):

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.

因此,形式上,在堆栈展开过程(包括析构函数)中调用可能处理异常的函数是完全有效的,但如果此类函数中的异常未被适当的 catch 块捕获,则std::terminate必须调用。