2008-11-23 87 views
8

我最近在這裏讀到一個關於靜態和動態鏈接的問題,這讓我想起了一些關於它的問題。從那篇文章中,我可以看到技術上的差異(包括直接的目標文件內容,而不僅僅是指向它),但我想更多地瞭解這樣做的優缺點。靜態鏈接優勢

前段時間,我的一位編程了好幾年的朋友感嘆C#沒有靜態鏈接,並說這是他期望未來版本最需要的功能。不幸的是,我是一個新手,並沒有真正理解這個說法。

感謝您的任何啓示!

回答

4

我不確定在C#中靜態鏈接是一個非常好的主意,說實話,有一百萬個原因。一個原因是,與C或C++等語言相反,C#具有程序集的概念,這些程序集基本上是可執行文件或DLL。

現在如果你想聯繫的事情靜態.NET中,你要麼

  • 合併類由多個組件到一個單一的組件。這會破壞很多東西,比如「內部」訪問修飾符。
  • 在同一個可執行文件中有多個程序集。這會使程序集的整個概念無用,並且需要重新設計.NET Framework中的反射方法。

我確定有一個聰明的方法來避免這些問題,但我不太清楚在.NET或Java之類的託管環境中的靜態鏈接。我的意思是,靜態鏈接確實提高了性能,但不是那麼多。無論如何,我們並不使用託管語言來提高執行速度。

另一個問題是DLL地獄,但在.NET中,這無疑是一個解決的問題。

+25

想要擁有一個.exe而不是一個.exe和30個.dll是一個非常好的理由 - 我的客戶不應該因爲想將我的軟件重構爲多個項目而拖動30多個文件。我不明白爲什麼你說的任何東西*都是這樣 - 他們可以基本上將.dll存儲在.exe中,並在需要時將其加載爲.dll。沒有理由不支持靜態鏈接。 – 2011-06-03 20:13:50

+2

我剛剛纔瞭解到F#實際上支持它。 – 2011-10-20 22:18:07

7

靜態可執行文件包含它需要的所有對象,因此執行時不會調用外部DLL。優點是無論在該系統上安裝了哪種版本的DLL,都可以在許多平臺上進行移植。 BIG的缺點是你很可能會浪費磁盤空間,因爲你在可執行代碼中包含了已存在於系統/外部DLL中的代碼。此外,我認爲,但我不太確定,只有一次DLL加載到主內存中,無論有多少可執行文件正在使用它們,但是如果靜態鏈接可執行文件中的庫對象,則會加載相同的代碼兩次(一次對於其他程序使用的DLL和一個用於可執行文件的DLL)。另一方面,這可能是一個優勢,而不是一個缺點,因爲可執行文件只包含它需要的外部庫的對象,而不是整個庫。當應用程序需要時,DLL作爲一個整體加載到內存中。

靜態鏈接是編譯小型應用程序的理想選擇,您希望將小型應用程序從一個系統傳輸到另一個系統作爲小型工具。即當它不包含在每個Linux發行版中時,對於我來說有一個靜態編譯版本的tcpdump是非常有用的。無論內核,glibc或其他系統庫的版本如何,它都必須在每個Linux上運行。也許它在Windows世界並沒有太多意義,因爲平臺更加同質化。如果您爲Windows XP/.NET vX.X編譯,它將在很多計算機上運行。如果你爲Debian X.X編譯一些東西,它肯定不適用於較舊/較新的Debian或Redhat等其他發行版。

這個thread也可以解決你的問題。

7

靜態鏈接的優點是它可以消除對庫的外部依賴性 - 即您正在使用的庫的行爲永遠不會改變,因爲有人在磁盤上更改了庫。這也是靜態鏈接的一個缺點。如果操作系統發生變化並且需要新版本的庫來正確使用它,則必須提供升級版本的二進制文件。同樣,如果將錯誤修復添加到庫中,如果靜態鏈接,則不會自動獲得該錯誤修復。

大多數(實際上可能是所有這些日子)​​操作系統可以爲多個進程加載一個動態庫的副本,這就是爲什麼在UNIX中它們被稱爲共享對象。

1

靜態鏈接與動態鏈接之間有一個很好的例子。如果您查看InkScape項目,您會發現InkscapePortable和InkScape。 InkscapePortable將運行一個USB棒。 InkScape不會。

2

所有需要的東西打包成一個可執行文件。所以,

  • 你不需要安裝任何其他的東西。只需複製並運行。或運行它在哪裏。沒有安裝程序,沒有告誡,由於錯誤的DLL版本沒有奇怪的錯誤。就這樣。
  • 此外,您的用戶可以享受這種簡單。這通常更重要。沒有人歡迎安裝依賴關係。特別是如果它像.NET框架一樣巨大。

當然可執行文件的大小會增加,但它應該小於一堆愚蠢的圖形文件。