2012-08-11 24 views
6

我有一個C++庫,我試圖用Clang在Mac OS X上運行。該庫由一個DLL和一個單元測試可執行文件組成。它編譯罰款與GCC和MSVC,與海灣合作委員會,我使用以下設置:捕獲派生的異常類型在Clang/MacOS上失敗X

  • 圖書館與-fvisibility=hidden
  • 編譯所有外露類被明確標記爲__attribute__(visibility("default"))
  • 圖書館有一些異常類,來自std::runtime_error。所有這些類都標記爲默認可見性。有一個根類LibraryException,從中派生出更多特定的異常。
  • 在GCC,我用-std=c++0x,鏗鏘,無論是庫和單元測試可執行文件是建立與-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) 

我覈實,我的自定義異常類的所屬類別和虛函數表使用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異常是從圖書館拋出它也沒有爲實例。

回答

3

這裏是正確的解決方案:

當應用可見性屬性,它必須同時適用時,當它被消耗的庫被編譯爲好。否則,客戶端將看不到這些類。對於升壓:: 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()析構函數幫助的事實是一些運氣,但它絕對不是正確的修復。

+0

絕對看起來像一個bug ...你自己重新聲明瞭析構函數還是默認構造的?使用gcc 4.3.2如果我從'exception'繼承時聲明一個沒有'throw()'說明符的析構函數,我會得到一個警告。 – 2012-08-11 10:20:06

+0

我在LibraryException中重新聲明它爲〜LibraryException()throw();否則,GCC 4.6會抱怨默認的拋出規格或類似的錯誤。 – Anteru 2012-08-11 10:47:24

相關問題