7

Clang を使用して Mac OS X で実行しようとしている C++ ライブラリがあります。このライブラリは、DLL と Unit-Test 実行可能ファイルで構成されています。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たとえば、ライブラリから例外がスローされた場合にも失敗します。

4

1 に答える 1

3

正しい解決策は次のとおりです。

可視性属性を適用する場合、ライブラリのコンパイル時と消費時の両方に適用する必要があります。そうしないと、クライアントにクラスが表示されません。boost::lexical_cast の場合、これは使用する必要があることを意味します

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

例外に a を追加してライブラリで修正されるまで__attribute((visibility("default")))(Boost 1.50 の時点で属性は存在しますが、Clang のサポートはまだないようです)。ライブラリのヘッダーで使用する場合は、クライアント コードで適切にキャッチできます。これ#pragmaは Clang でも機能します。

throw () デストラクタの指定が役に立ったという事実は運が良かったのですが、それは間違いなく正しい修正ではありません。

于 2012-08-11T09:08:00.800 に答える