複製鏈接
請複製以下鏈接發送給好友

DLL地獄

鎖定
在計算中,DLL地獄(DLL Hell)是使用與Microsoft Windows操作系統一起使用的動態鏈接庫(DLL)時出現的複雜性的術語,特別是傳統的16位版本,它們都在單個內存空間中運行。
DLL Hell可以通過許多不同的方式表現出來,其中應用程序無法啓動或正常工作。
DLL Hell是Windows生態系統特定形式的一般概念依賴地獄。
中文名
DLL地獄
外文名
DLL Hell

DLL地獄問題

DLL是Microsoft的共享庫實現。共享庫允許將公共代碼捆綁到包裝器DLL中,並由系統上的任何應用程序軟件使用,而無需將多個副本加載到內存中。一個簡單的例子可能是GUI文本編輯器,它被許多程序廣泛使用。通過將此代碼放在DLL中,系統上的所有應用程序都可以使用它而無需使用更多內存。這與靜態庫形成對比,靜態庫功能相似,但將代碼直接複製到應用程序中。在這種情況下,每個應用程序都會增加它使用的所有庫的大小,對於現代程序來説這可能非常大。
當計算機上的DLL版本與創建程序時使用的版本不同時,會出現問題。 DLL沒有用於向後兼容的內置機制,甚至對DLL的微小更改使其內部結構與以前的版本不同,嘗試使用它們通常會導致應用程序崩潰。靜態庫避免了這個問題,因為用於構建應用程序的版本包含在其中,因此即使系統上的其他位置存在較新的版本,這也不會影響應用程序。
版本不兼容的一個關鍵原因是DLL文件的結構。該文件包含DLL中包含的各個方法(過程,例程等)的目錄以及它們獲取和返回的數據類型。即使對DLL代碼進行微小的更改也可能導致重新排列此目錄,在這種情況下,調用特定方法的應用程序認為它是目錄中的第4項可能最終會調用完全不同且不兼容的例程,這會通常會導致應用程序崩潰。
DLL經常遇到一些問題,特別是在系統上安裝和卸載了許多應用程序之後。困難包括DLL版本之間的衝突,難以獲得所需的DLL,以及具有許多不必要的DLL副本。

DLL地獄原因

DLL不兼容的原因是:
內存限制,以及16位版本的Windows中缺少進程內存空間的分離;
缺乏針對DLL的強制標準版本控制,命名和文件系統位置模式;
缺乏用於軟件安裝和刪除的強制標準方法(包管理);
缺乏對DLL應用程序二進制接口管理和安全措施的集中權威支持,允許發佈具有相同文件名和內部版本號的不兼容DLL;
過度簡化的管理工具,防止用户和管理員識別已更改或有問題的DLL;
開發人員破壞共享模塊中函數的向後兼容性;
Microsoft發佈對操作系統運行時組件的帶外更新;
早期版本的Windows無法運行同一個庫的並行衝突版本;
依賴於當前目錄或%PATH%環境變量,它們隨時間和系統而變化,以查找相關的DLL(而不是從顯式配置的目錄中加載它們);
開發人員將示例應用程序中的ClassID重用於其應用程序的COM接口,而不是生成自己的新GUID。
DLL Hell在Windows NT之前版本的Microsoft操作系統上是一種非常普遍的現象,主要原因是16位操作系統沒有將進程限制到自己的內存空間,因此不允許它們加載自己的版本的他們兼容的共享模塊。在覆蓋現有系統DLL之前,應用程序安裝程序應該是好公民並驗證DLL版本信息。 Microsoft和其他第三方工具供應商提供了簡化應用程序部署的標準工具(始終涉及運送相關的操作系統DLL)。在授予使用Microsoft徽標之前,Microsoft甚至要求應用程序供應商使用標準安裝程序並使其安裝程序經過認證,以使其正常工作。良好的公民安裝方法並沒有緩解這個問題,因為互聯網普及的增加為獲得不合格的應用程序提供了更多的機會。

DLL地獄解決方案

多年來,各種形式的DLL地獄已經被解決或減輕。

DLL地獄靜態鏈接

應用程序中DLL Hell的一個簡單解決方案是靜態鏈接所有庫,即包含程序中所需的庫版本,而不是選擇具有指定名稱的系統庫。這在C / C ++應用程序中很常見,其中不必擔心安裝了哪個版本的MFC42.DLL,而是將應用程序編譯為靜態鏈接到相同的庫。這完全消除了DLL,並且可以在僅使用提供靜態選項的庫的獨立應用程序中實現,就像Microsoft基礎類庫一樣。然而,犧牲了DLL的主要目的,即程序之間的運行時庫共享以減少內存開銷。在多個程序中複製庫代碼會導致軟件膨脹,並使安全修復程序或更新版本的相關軟件的部署變得複雜。

DLL地獄Windows文件保護

使用Windows文件保護(WFP)在Windows 2000中引入了DLL覆蓋問題(微軟稱為DLL Stomping)。這可以防止未經授權的應用程序覆蓋系統DLL,除非它們使用允許此操作的特定Windows API。可能仍存在Microsoft的更新與現有應用程序不兼容的風險,但通過使用並排程序集,當前版本的Windows通常會降低此風險。
第三方應用程序無法踩踏操作系統文件,除非它們將合法的Windows更新與其安裝程序捆綁在一起,或者如果它們在安裝期間禁用了Windows文件保護服務,並且在Windows Vista或更高版本中也取得系統文件的所有權並授予自己訪問權限。 SFC實用程序可以隨時還原這些更改。

DLL地獄同時運行衝突的DLL

這裏的解決方案包括為磁盤和內存中的每個應用程序提供相同DLL的不同副本。
一個簡單的手動解決方案是將問題DLL的不同版本放入應用程序的文件夾中,而不是通用的系統範圍文件夾。只要應用程序是32位或64位,並且DLL不使用共享內存,這通常可以正常工作。對於16位應用程序,這兩個應用程序不能在16位平台上同時執行,也不能在32位操作系統下的同一個16位虛擬機中同時執行。 OLE在Windows 98 SE / 2000之前阻止了這一點,因為早期版本的Windows為所有應用程序都有一個COM對象註冊表。Windows 98 SE / 2000引入了一種稱為並行程序集的解決方案,它為每個需要它們的應用程序加載單獨的DLL副本(從而允許需要衝突的DLL的應用程序同時運行)。這種方法通過允許應用程序將模塊的唯一版本加載到其地址空間中來消除衝突,同時保留通過使用內存映射技術在仍然執行的不同進程之間共享公共代碼來共享應用程序之間的DLL(即減少內存使用)的主要好處使用相同的模塊。然而,在多個進程之間使用共享數據的DLL不能採用這種方法。一個負面影響是DLL的孤立實例可能無法在自動化過程中更新 [1] 

DLL地獄便攜式應用

根據應用程序體系結構和運行時環境,可移植應用程序可能是減少某些DLL問題的有效方法,因為每個程序都捆綁了自己所需的任何DLL的私有副本。該機制依賴於應用程序在加載它們時沒有完全限定依賴DLL的路徑,並且操作系統在任何共享位置之前搜索可執行目錄。然而,這種技術也可以被惡意軟件利用,如果私有DLL沒有以與共享DLL相同的方式保持最新的安全補丁,則增加的靈活性也可能以犧牲安全性為代價。
應用程序虛擬化還允許應用程序在“泡沫”中運行,這避免了將DLL文件直接安裝到操作系統的文件系統中。
參考資料