延遲載入D L L

2021-04-01 22:17:11 字數 3632 閱讀 9934

延遲載入d l l

------amoon100 2005/10/16

microsoft visual c++ 6.0提供了乙個出色的新特性,它能夠使dll的操作變得更加容易。這個特性稱為延遲載入dll。延遲載入的dll是個隱含鏈結的dll,它實際上要等到你的**試圖引用dll中包含的乙個符號時才進行載入。延遲載入的dll在下列情況下是非常有用的:

1)如果你的應用程式使用若干個dll,那麼它的初始化時間就比較長,因為引導程式要將所有需要的d l l對映到程序的位址空間中。解決這個問題的方法之一是在程序執行的時候分開載入各個dll。延遲載入的dll能夠更容易地完成這樣的載入。

2)如果呼叫**中的乙個新函式,然後試圖在老版本的系統上執行你的應用程式,而該系統中沒有該函式,那麼引導程式就會報告乙個錯誤,並且不允許該應用程式執行。你需要一種方法讓你的應用程式執行,然後,如果(在執行時)發現該應用程式在老的系統上執行,那麼你將不呼叫遺漏的函式。例如,乙個應用程式在windows 2000上執行時想

要使用psapi函式,而在windows 98上執行想要使用toolhelp函式(比如process32next)當該應用程式初始化時,它呼叫getversionex函式來確定主作業系統,並正確地呼叫相應的其他函式。如果試圖在windows 98上執行該應用程式,就會導致引導程式顯示一條錯誤訊息,因為windows 98上並不存在psapi.dll模組。同樣,延遲載入的dll能夠使你

非常容易地解決這個問題。

下面讓我們從比較容易的操作開始介紹,也就是使延遲載入dll能夠執行。首先,你象平常那樣建立乙個dll。也要象平常那樣建立乙個可執行模組,但是必須修改兩個鏈結程式開關,並且重新鏈結可執行模組。下面是需要新增的兩個鏈結程式開關:

/lib:delayimp.lib

/delayload:mydll.dll

1)從可執行模組的輸入節中刪除mydll.dll,這樣,當程序被初始化時,作業系統的引導程式就不會顯式載入dll。

2)將新的delay import(延遲輸入)節(稱為.didata)嵌入可執行模組,以指明哪些函式正在從mydll.dll的輸入。

3)通過轉移到對- - delayloadhelper函式的呼叫,轉換到對延遲載入函式的呼叫。當應用程式執行時,對延遲載入函式的呼叫實際上是對- -delay loadhelper函式的呼叫。該函式引用特殊的delay import節,並且知道呼叫loadlibrary之後再呼叫getprocaddress。一旦獲得延遲載入函式的位址, - - delayloadhelper就要安排好對該函式的呼叫,這樣,將來的呼叫就會直接轉向對延遲載入函式的呼叫。注意,當第一次呼叫同乙個dll中的其他函式時,必須對它們做好安排。另外,可以多次設定/delayload鏈結程式的開關,為想要延遲載入的每個dll設定一次開關。

好了,整個操作過程就這麼簡單。但是還應該考慮另外兩個問題。通常情況下,當作業系統的引導程式載入可執行模組時,它將設法載入必要的d l l。如果乙個dll無法載入,那麼引導程式就會顯示一條錯誤訊息。如果是延遲載入的dll,那麼在進行初始化時將不檢查是否存

在dll。如果呼叫延遲載入函式時無法找到該dll,- -delayloadhelper函式就會引發乙個軟體異常條件。可以使用結構化異常處理(seh)方法來跟蹤該異常條件。如果不跟蹤該異常條件,那麼你的程序就會終止執行.當- -delayloadhelper確實找到你的dll,但是要呼叫的函式不在該dll中時,將會出現另乙個問題。比如,如果引導程式找到乙個老的d l l版本,就會發生這種情況。在這種情況下,- - delayloadhelper也會引發乙個軟體異常條件,對這個軟體異常條件的處理方法與上面相

同。下一節介紹的示例應用程式顯示了如何正確地編寫seh**以便處理這些錯誤。你會發現**中有許多其他元素,這些元素與seh和錯誤處理毫無關係。但是這些元素與你使用延遲載入的dll時可以使用的輔助特性有關。下面將要介紹這些特性。如果你不使用更多的高階特性,可以刪除這些額外的**。

如你所見, visual c++ 開發小組定義了兩個軟體異常條件**,即vcppexception(error_severity_error,error_mod_not_found)和vcppexception(error_severity_error、error_proc_not_found)。這些**分別用於指明dll模組沒有找到和函式沒有找到。

到現在為止,已經講述了如何使用延遲載入的dll和正確解決錯誤條件的基本方法。但是microsoft的延遲載入dll的實現**超出了迄今為止我已講述的內容範圍。比如,你的應用程式能夠解除安裝延遲載入的dll。假如你的應用程式需要乙個特殊的dll來列印乙個文件,那麼這個dll就非常適合作為乙個延遲載入的dll,因為大部分時間它是不用的。不過,如果使用者選擇了print命令,你就可以呼叫該dll中的乙個函式,然後它就能夠自動進行dll的載入。這確實很好,但是,當文件列印後,使用者可能不會立即列印另乙個文件,因此可以解除安裝這個dll,釋放系統的資源。如果使用者決定列印另乙個文件,那麼dll就可以根據使用者的要求再次載入,若要解除安裝延遲載入的dll,必須執行兩項操作。首先,當建立可執行檔案時,必須設定另乙個鏈結程式開關( /delay:unload)。其次,必須修改源**,並且在你想要解除安裝dll時呼叫- -

funloaddelayloaded dll函式:

/delay:unload鏈結程式開關告訴鏈結程式將另乙個節放入檔案中。該節包含了你清除已經呼叫的函式時需要的資訊,這樣它們就可以再次呼叫- - delayloadhelper函式。當呼叫- -

funloaddelayloaded dll時,你將想要解除安裝的延遲載入的dll的名字傳遞給它。該函式進入檔案中的未解除安裝節,並清除dll的所有函式位址,然後- - funloaddelayloaded dll呼叫freelibrary,以便解除安裝該dll。

下面要指出一些重要的問題。

**首先,千萬不要自己呼叫freelibrary,來解除安裝dll,否則函式的位址將不會被清除,這樣,當下次試圖呼叫dll中的函式時,就會導致訪問違規。

**第二,當呼叫- -funloaddelayloaded dll時,傳遞的dll名字不應該包含路徑,名字中的字母必須與你將dll名字傳遞給/delayload鏈結程式開關時使用的字母大小寫相同,否則, - - funloaddelayloaded dll的呼叫將會失敗。

**第三,如果永遠不打算解除安裝延遲載入的dll,那麼請不要設

定/delay:unload鏈結程式開關,並且你的可執行檔案的長度應該比較小。

**最後,如果你不從用/delay:unload開關建立的模組中呼叫- - funloaddelayloaded dll,那麼什麼也不會發生, - -

funloaddelayloaded dll什麼操作也不執行,它將返回false。

延遲載入的dll具備的另乙個特性是,按照預設設定,呼叫的函式可以與一些記憶體位址相鏈結,在這些記憶體位址上,系統認為函式將位於乙個程序的位址中。由於建立可鏈結的延遲載入的dll節會使你的可執行檔案變得比較大,因此鏈結程式也支援乙個/delay:nobind開關。因為人們通常都喜歡進行鏈結,因此大多數應用程式不應該使用這個鏈結開關。

延遲載入的dll的最後乙個特性是供高階使用者使用的,它真正顯示了m i c r o s o f t的注意力之

所在。當- - delayloadhelper函式執行時,它可以呼叫你提供的掛鉤函式。這些函式將接收- -

delayloadhelper函式的進度通知和錯誤通知。此外,這些函式可以過載dll如何載入的方法以及如何獲取函式的虛擬記憶體位址的方法。

(摘自<

多個dll延遲載入

1.新增delayimp.lib 2.新增要延遲載入的dll 3.設定解除安裝選項。4.多個dll放置的目錄設定 如下 4.設定dll延遲載入的目錄 class cdelaydll unsigned long size getmodulefilename getmodulehandle xdatap...

懶載入 延遲載入

概念 為了推遲和資料庫互動的時間,推遲到真正需要這個物件資料的時候。提高系統的效能 通過 asm和cglib二個jar包實現懶載入。domain是非final的 1 session.load懶載入 1 返回的是乙個 物件,new關鍵字來建立乙個 物件,理解成乙個快捷方式,不是真正的類,而是 類。2 ...

靜態載入dll和動態載入dll

一,首先編寫dll 建win32空dll工程 標頭檔案.h extern c declspec dllexport int max int a,int b extern c 解決函式名由於不同編譯器造成的名字匹配問題,通常c 編譯器編譯時會對函式進行改名,而c編譯器不會 extern c decls...