【发布时间】:2011-04-07 23:36:57
【问题描述】:
我正在与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 << "... handler\n";
}
}
}
// 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 上不会发生,即使运行完全相同的命令也是如此。
问题:
- 为什么会发生这种情况?这是一个错误、未定义的行为还是设计使然?
- 如果没有链接到库,我怎样才能使它工作?
非常感谢。
【问题讨论】:
-
如果您所说的“未定义行为”是指根据 C++ 标准,那么它(充其量)是实现定义的,当您使用将编译器置于非兼容模式的编译器选项时会发生什么。我怀疑这对您有多大帮助,但是您不能禁用标准的某些部分,然后期望标准对您有所帮助;-)
标签: c++ macos gcc shared-libraries rtti