在异常处理期间键入分辨率

imr*_*eal 6 c++ exception-handling exception

当抛出异常C++并且堆栈被解开时,如何选择正确的处理程序(catch子句)来处理异常?

void f1()
{
    throw 1;
}

void f2()
{
    try
    {
        f1();
    }
    catch(const char* e)
    {
        std::cout << "exc1";
    }
}

...
try
{
    f2();
}
catch(int& e)
{
    std::cout << "exc2";
}
...
Run Code Online (Sandbox Code Playgroud)

例如,这个代码不出所料地打印,"exc2"因为catch(int& e)它能够处理1 int类型化的对象.

我不明白的是,这怎么可以静态解决?还是动态解决?是否传播了类型信息?

zne*_*eak 3

对于大多数事情,C++ 标准没有指定实现,但限制了有效的实现。不会有一个了解具体细节的通用答案。

Itanium ABI 是一种流行的 ABI,它提供与语言无关的异常支持。在该实现中,展开 API 调用堆栈帧的个性函数,该函数接收异常上下文、异常结构以及对指导 catch 行为的异常处理表的引用。根据程序异常表中调用的返回地址查找个性函数;假设唯一可以引发异常的指令是调用指令。(GCC 具有允许通过启用“非调用异常”从信号处理程序中抛出异常的扩展。)使用 Itanium ABI 的编译器提供了一个个性函数,该函数知道如何检查异常对象的运行时类型,并将该类型与元素进行比较的异常表。

还有其他方法可以做到这一点。例如,在 32 位 Windows 上,异常处理通过在堆栈上设置处理函数作为链接列表项来工作。这些链表节点包含异常处理程序的地址,它们使用EXCEPTION_RECORD来确定从那里去哪里。不幸的是,我自己对细节的了解有点少。

顺便说一下,Itanium ABI 并不是 C++ 所独有的。例如,在 Apple 平台上,Objective-C 代码也使用 Itanium ABI 来处理异常。这有一个有趣的特性,即任何一种语言中的 catch-all 子句都可以捕获另一种语言中的异常。