【问题标题】:Catching derived exceptions types fails on Clang/MacOS X在 Clang/MacOS X 上捕获派生异常类型失败
【发布时间】:2012-08-08 10:24:38
【问题描述】:

我有一个 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 上,单元测试框架现在会失败,因为异常类型错误。 IE。像这样的测试失败了:

// 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 异常时,它也会失败。

【问题讨论】:

    标签: c++ macos clang porting


    【解决方案1】:

    这是正确的解决方案:

    应用可见性属性时,必须在编译库时以及使用时都应用它。否则,客户端将看不到这些类。对于 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。

    指定 throw () 析构函数有所帮助的事实是一些运气,但这绝对不是正确的解决方法。

    【讨论】:

    • 绝对看起来像一个错误......你是自己重新声明了析构函数还是默认构造的?使用 gcc 4.3.2,如果我在从 exception 继承时声明没有 throw() 说明符的析构函数,我会收到警告。
    • 我在 LibraryException 中重新声明为 ~LibraryException () throw ();否则,GCC 4.6 会抱怨默认的抛出规范或类似的东西不正确。
    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多