2012-08-11 10 views
6

私はClangのMac OS Xで動作させようとしているC++ライブラリを持っています。ライブラリは、DLLとUnit-Test実行可能ファイルで構成されています。これは、GCCと、私は次の設定を使用し、GCCとMSVCで罰金コンパイル:Clang/MacOS X

  • ライブラリはすべての露出のクラスが明示的に__attribute__(visibility("default"))
  • としてマークされている-fvisibility=hidden
  • でコンパイルされているライブラリは、いくつかの例外クラスを持っています、 std::runtime_errorに由来する。そのようなクラスはすべてデフォルトの可視性のためにマークされています。より具体的な例外が引き出されるルートクラスLibraryExceptionがあります。 GCCで
  • 例外が間違った型であるので、私は、打ち鳴らすと、ライブラリやユニットテストの実行可能ファイルの両方がMac OS Xで-stdlib=libc++ -std=c++11

で構築されて、ユニットテストフレームワークは、今失敗し、-std=c++0xを使用。私。このようなテストは失敗します。

// 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フレームワークを使用しています。 boost::lexical_cast例外がライブラリからスローされたときには、インスタンスで障害が発生した

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"; 
} 

小さなテストプログラムは、同じ問題を呈します。ここで

答えて

3

は正解です:

visibility属性を適用する場合、それが適用されなければならないの両方それが消費されると、ライブラリも同様にコンパイルされたとき。それ以外の場合、クライアントはクラスを表示しません。ブースト:: lexical_castはについては、これは、属性が存在しているが、それはと思われますが、彼らはそれはブースト1.50のよう(例外に__attribute((visibility("default")))を追加することにより、ライブラリに固定されるまで、

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

を使用しなければならないことを意味しますClangのサポートはまだありません)。ライブラリ内のヘッダーで使用すると、クライアントコードで正しく捕捉できます。この#pragmaはClangでも動作します。

throw()デストラクタを指定することは助けになりましたが、確かに正しい解決策ではありません。

+0

間違いなくバグのように見えます...デストラクタを自分で再宣言しましたか、デフォルトの構築済みですか? gcc 4.3.2では、 'exception'から継承するときに' throw() '指定子なしでデストラクタを宣言すると、警告が表示されます。 –

+0

私はそれを〜LibraryException()のようにLibraryExceptionで再宣言しました。さもなければ、GCC 4.6はデフォルトのものが間違ったスロー指定かそれに類似するものを持っていると訴えました。 – Anteru

関連する問題