gpt4 book ai didi

c++ - 编译器如何知道使用哪个 catch block ?

转载 作者:可可西里 更新时间:2023-11-01 17:49:22 24 4
gpt4 key购买 nike

假设我有以下两个文件,main.cpp:

#include <iostream>

class A {};
void foo();

int main(void)
{
try {
foo();
}
catch(const A& e) {
std::cout << "Caught an A." << std::endl;
}
return 0;
}

foo.cpp:

class A {};
class B : public A {};

void foo()
{
B b;
throw b;
}

现在,当我分别编译这些文件中的每一个、链接生成的目标文件并运行生成的可执行文件时,我得到了预期的结果:

$ clang++ --std=c++14 -c main.cpp
$ clang++ --std=c++14 -c foo.cpp
$ clang++ --std=c++14 main.o foo.o
$ ./a.out
Caught an A.

这让我大吃一惊! A 类没有虚方法。因此,它不是多态的,它的实例在运行时不应该携带任何类型信息。 main.o 目标文件不知道抛出什么,因为实际抛出发生在 foo() 内部,其主体在单独的编译单元中定义。 foo.o 对象文件有更多信息,但同样不知道任何 catch 语句和捕获异常的预期类型。

简而言之:我看不出这两个分别编译然后链接的源文件如何在没有一些运行时类型信息可供使用的情况下产生上述输入。单独编译的文件都不应该有足够的信息来获取正确的 catch block 。

最佳答案

这当然完全依赖于编译器。

所有编译器的约束是:

  • 异常的类型在您抛出时是已知的(在编译时,或者在运行时,如果您抛出一个多态对象)。
  • 适用的 catch block (它们可以是多个)及其类型取决于执行路径。

这意味着必须在运行时识别类型,即使异常对象是非多态的。

实现此目的的一种简单方法是将指向 typeinfo 对象的指针与抛出的对象本身一起传递。这是 GCC 使用的方法:参见 online code ,这里是为方便起见在 foo() 中的摘录:

    call    __cxa_allocate_exception
mov edx, 0
mov esi, OFFSET FLAT:typeinfo for B ; <== !!
mov rdi, rax
call __cxa_throw

关于c++ - 编译器如何知道使用哪个 catch block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40795291/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com