2013-08-02 58 views
0

我們已經將我們的Java和.NET API庫轉換爲C++,並試圖找出將編譯版本分發給其他開發人員以使用其定製應用程序的最佳方法。它應該是一個靜態庫還是動態庫?我們需要爲Win32和Win64創建(並且我假設每個目標操作系統的Debug和Release版本)。鑑於我遇到過的所有挫折,試圖確保所有引用的庫匹配(/ MT與/ MD),我想知道是否有決定在這裏爲其他開發人員簡化它。分發Windows C++庫:如何決定是創建靜態庫還是動態庫?

當我在一個靜態庫上運行dumpbin /all <static library file name> | find /i "msvc時,沒有看到任何運行時引用(與我在.exe或.dll上執行相同操作時不同)。這是否表示運行時尚未鏈接,並且在開發和構建自己的應用程序時,開發人員能夠更靈活地製作/ MT還是/ MD?

哪種方法會使開發人員的生活更輕鬆?

+2

通常是一個好主意,提供兩者。 –

+0

看起來好像都是這樣,並且在每種風格(調試/發佈,以及所有CRT版本)中都是所謂的。 「 –

回答

3

靜態和動態(共享)庫都有顯着的優勢。也許有一種選擇是分發這兩種類型的庫,並讓庫用戶決定使用哪種庫。

對於我自己,我通常使用靜態庫,除非我認爲動態庫的優勢對項目有意義。

在一個靜態庫的優點:

  • 一旦在編譯時由庫的用戶鏈接中,在庫中的代碼總是需要調用它同一模塊中。所以沒有DLL地獄,也沒有並肩地獄。我無法統計我嘗試在Windows上運行程序的次數,只是因爲我沒有安裝正確版本的MSVC運行時(DLL)而失敗。這實在是一種痛苦,如果可以避免,它會讓每個人的生活更輕鬆。
  • 同樣,庫中代碼的符號最終將在調用庫的模塊的.pdb中,而不是另一個.pdb(.dll的.pdb)中,您必須跟蹤,複製等
  • 這是次要的,但對於靜態庫,只有需要鏈接它的函數/數據最終在可執行文件中。而對於DLL,它是整個辣醬玉米餅餡。

在動態庫

  • 的明顯優勢的優點是,它允許該庫在運行時被替換,甚至由最終用戶,而不進行鏈接。
  • 在大多數環境中這是次要的,但是如果很多可執行文件都將庫鏈接起來,擁有DLL意味着更少的磁盤空間,因爲相同的數據/代碼不會在每個可執行文件中重複。
  • 有些東西並不總是值得讚賞的:if該庫將被多個進程同時加載,並將其作爲DLL提供 - 理想情況下 - 只有一個只讀數據副本(甚至是可寫數據直到並且除非它被特定進程寫入)都需要在內存中。運行時鏈接DLL的所有進程在內存中共享相同的字節。共享內存爲均爲總虛擬內存(RAM +頁面文件)物理內存。然而,這僅僅是最好的情況 - 如果DLL不能在兩個進程中的相同虛擬地址上加載,則它們不能共享它。
+0

」同樣,調​​用庫的模塊的.pdb中的符號。「我沒有按照你的意見說話。你能否詳細說明一下? –

+0

嗨,山姆,看起來像這樣的陳述不清楚我寫的方式,我現在編輯它。讓我知道它是否仍然沒有意義。 –

3

靜態庫更容易創建,但太多難以分配。客戶端程序員會將他們鏈​​接到他的程序中,因此編譯設置與他的兼容性非常重要。您必須分發至少4個版本,與4種不同的CRT版本(/ MD,/ MDd,/ MT,/ MTd)相對應。而且您需要將其乘以常用Visual Studio版本的數量。如果你不知道客戶端程序員要使用什麼,那麼這可能是一個非常大的列表。

未與DLL一個問題,你只提供導出的函數聲明一個.H,一個.LIB這是DLL的導入庫(無碼,只包含名稱)和.dll文件本身。

然而,很難爲您的DLL創建一個可用於任何C或C++編譯器的接口。你不能公開任何標準的C++庫類,返回一個std :: string不會起作用。你不能創建任何分配需要由調用者釋放的內存的函數。一般情況下你不能跨越邊界拋出異常。做這些事情往往會導致非常難以診斷客戶端程序員的運行時問題,這是由於內存分配器和類對象佈局不匹配造成的。 COM對象模型就是這種接口的一個例子。

這不是你使用靜態庫時遇到的問題。有點意外,他們要求運行時和編譯器版本匹配。如果客戶端程序員被一個錯誤的靜態庫所困住,那麼他也會遇到所有這些問題。和更多。靜態庫就像少女性。你犯一個錯誤,並最終支持你的餘生。

+0

嗨漢斯,你能解釋一下爲什麼,我用我建立的靜態庫,我不能使用'dumpbin'來顯示它爲哪個運行時構建的?沒有看到msvv *的任何引用使我認爲運行時被推遲到圖書館被鏈接。 –

+0

運行時依賴關係通過原始源代碼中的#includes間接進行。它是鏈接器,它釘了下來。 #包括一個版本的標題,但與另一個版本鏈接是問題,不匹配會產生非常難看的鏈接器錯誤。對於VS2005和VS2008,您可以看到它,因爲清單鏈接指令。但是在VS2010中又被刪除了。有另一種方式來執行它,你會得到一個/ FAILIFMISMATCH鏈接器錯誤。這是最終的鏈接地獄,你會得到一個支持電話。 –

+0

Visual Studio是否根據您選擇的運行時更改您引用的#​​include文件的基本目錄? –