在Mac OS X上的-fno-rtti共享库中多态捕获异常
我正在用
f-no-rtti
建立一个共享库。在内部,这个库抛出std:invalid_argument
并捕获std::exception
,但是从未输入catch
子句。
以下代码重现了该问题(g ++ 4.2,Mac OS X 10.6):
// library.cpp: exports f(), compiled with -fno-rtti
#include <stdexcept>
#include <iostream>
extern "C" {
void f() {
try {
throw std::invalid_argument("std::exception handler");
} catch( std::exception& e) {
std::cout << e.what() << "n";
} catch(...) {
std::cout << "... handlern";
}
}
}
// main.cpp: the main executable, dynamically loads the library
#include <dlfcn.h>
typedef void(*fPtr)();
int main() {
void* handle = dlopen( "./libexception_problem.dylib", RTLD_LAZY );
fPtr p_f = reinterpret_cast<fPtr>( dlsym( handle, "f" ) );
p_f();
}
输出:
MacBook-Pro:teste pfranco$ # works fine with rtti
MacBook-Pro:teste pfranco$ g++ -c library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ main.cpp -o main && ./main
std::exception handler
MacBook-Pro:teste pfranco$ # breaks with -fno-rtti
MacBook-Pro:teste pfranco$ g++ -c -fno-rtti library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ -fno-rtti main.cpp -o main && ./main
... handler
MacBook-Pro:teste pfranco$ #-no_dead_strip_inits_and_terms doesn't change anything
MacBook-Pro:teste pfranco$ g++ -c -no_dead_strip_inits_and_terms -fno-rtti library.cpp && g++ -no_dead_strip_inits_and_terms -shared -o libexception_problem.dylib library.o && g++ -fno-rtti -no_dead_strip_inits_and_terms main.cpp -o main && ./main
... handler
MacBook-Pro:teste pfranco$ # linking against the shared library works, but this isn't always an option
MacBook-Pro:teste pfranco$ g++ -c -fno-rtti library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ -fno-rtti main.cpp -o main -L. -lexception_problem && ./main
std::exception handler
只有当抛出的代码在共享库中时才会发生这种情况,并且只有当捕获的类型是实际异常的基类时才会发生 - catch(std::invalid_argument&)
工作正常,std::logic_error&
没有。
有趣的是,即使在运行完全相同的命令时,这也不会发生在Linux上。
问题:
为什么会这样?这是一个错误,未定义的行为还是设计?
如果没有链接到图书馆,我怎么能让它工作?
非常感谢。
没有找到相关结果
已邀请:
2 个回复
购藏盗码韦
掏得透垦滩
禁止使用虚拟生成有关每个类的信息 函数供C ++运行时类型标识功能使用 (
和
)。如果你不使用那些部分 语言,您可以使用此标志来节省一些空间。注意 异常处理使用相同的信息,但它会 根据需要生成它。
操作员仍然可以 用于不需要运行时类型信息的强制转换,即 施放到
或明确的基类。 RTTI是该语言的核心部分。如果编译器允许您禁用它,那么您在语言规则之外工作,因此不一定能使所有内容按预期工作。