捕获派生异常类型在 Clang/MacOS X 上失败

Catching derived exceptions types fails on Clang/MacOS X

本文关键字:MacOS 失败 Clang 派生 异常 类型      更新时间:2023-10-16

我有一个C++库,我正在尝试使用Clang在Mac OS X上运行。该库由一个 DLL 和一个单元测试可执行文件组成。它使用 GCC 和 MSVC 编译得很好,使用 GCC,我使用以下设置:

  • 该库使用 -fvisibility=hidden
  • 编译
  • 所有公开的类都显式标记为__attribute__(visibility("default"))
  • 该库有一些异常类,派生自std::runtime_error 。所有此类类都标记为默认可见性。有一个根类LibraryException从中派生更具体的异常。
  • 在 GCC 上,我使用 -std=c++0x ,带有 clang,库和单元测试可执行文件都是用-stdlib=libc++ -std=c++11构建

在 Mac OS X 上,单元测试框架现在失败,因为异常类型错误。 即这样的测试失败:

// bla.foo () throws CustomException, which is derived from LibraryException
TEST_THROWS (bla.foo (), CustomException)
// This works however
TEST_THROWS (bla.foo (), LibraryException)

我验证了我的自定义异常类的 typeinfo 和 vtable 是否使用 nm -g library.dylib | c++filt -p -i 导出。似乎所有例外情况都是如此...这到底是怎么回事?我试图对错误的进行调试,我看到如何在库中抛出正确的类型,但单元测试可执行文件中无法捕获相同的类型。Clang有什么特别的要求才能使它工作吗?我正在使用SVN最新的googletest框架进行测试。

一个小型测试程序也表现出同样的问题:

try {
    funcThatThrowsCustomExceptionFromLibraryDylib ();
} catch (CustomException& e) {
    // doesn't get here
} catch (LibraryException& e) {
    // does get here
    // after demangle, this prints CustomException
    // Can cast down to CustomException and access the fields as well
    std::cout << typeid (e).name () << "n";
}

例如,当从库中引发boost::lexical_cast异常时,它也失败。

这是正确的解决方案:

应用可见性属性时,必须在编译库时以及使用库时应用该属性。否则,客户端将看不到这些类。对于 boost::lexical_cast,这意味着您必须使用

 #pragma GCC visibility push(default)
 #include <boost/lexical_cast.hpp>
 #pragma GCC visibility pop

直到他们通过在异常中添加__attribute((visibility("default")))在库中修复它(从 Boost 1.50 开始,该属性存在,但似乎还没有对 Clang 的支持)。在库中的标头中使用它时,可以在客户端代码中正确捕获它。这个#pragma也适用于Clang。

指定抛出 () 析构函数这一事实有所帮助,但这绝对不是正确的解决方案。