Wit*_*iko 8 c++ compiler-construction exception
假设我有以下两个文件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;
}
Run Code Online (Sandbox Code Playgroud)
并且foo.cpp:
class A {};
class B : public A {};
void foo()
{
B b;
throw b;
}
Run Code Online (Sandbox Code Playgroud)
现在,当我单独编译每个文件时,链接生成的目标文件,并运行生成的可执行文件,我得到预期的结果:
$ 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.
Run Code Online (Sandbox Code Playgroud)
那令我难以置信!类A没有虚方法.因此,它不是多态的,并且其实例在运行时不应携带任何类型信息.该main.o目标文件是不知道被扔到什么,因为实际投掷发生里面foo(),他的尸体在一个单独的编译单元定义.该foo.o目标文件提供了更多信息,但同样不知道任何catch语句和预期的类型捕获的异常的.
简而言之:我没有看到两个源文件如何单独编译然后链接可以产生上述输入,而不需要处理一些运行时类型信息.单独编译的文件都没有足够的信息来获取正确的catch块.
这当然完全取决于编译器.
所有编译器的约束是:
这意味着必须在运行时识别类型,即使异常对象是非plymorphic.
实现此目的的一种简单方法是将指针typeinfo与抛出的对象本身一起传递给对象.这是GCC使用的方法:参见在线代码,这里是foo()为方便起见而提取的内容:
call __cxa_allocate_exception
mov edx, 0
mov esi, OFFSET FLAT:typeinfo for B ; <== !!
mov rdi, rax
call __cxa_throw
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
374 次 |
| 最近记录: |