[英]Delphi unit initialization not always called
我在.bpl中有一個單元,我需要一個字符串列表來表示我編寫的新函數。 我希望stringlist在應用程序的生命周期內保持不變,這樣每個調用都可以建立在之前調用的內容之上。
所以它在單元內全局聲明,我在Initialization部分初始化它,如下所示:
var
ProductLookup : TStrings;
...
function foo : boolean;
begin
result := (ProductLookup.IndexOfName('bar') >=0); //blow up here. It's nil. Why?
end;
....
initialization
ProductLookup := TStringList.Create; // This should get run, but doesn't.
finalization
FreeAndNil(ProductLookup);
end.
當我對它進行單元測試時,一切都很好。 但是當它從主應用程序運行時,由於字符串列表為零而導致訪問沖突。 所以現在我在foo函數中檢查nil並在必要時創建。 但我不知道為什么初始化對我不起作用。 我在初始化中放了一個調試消息,當它作為BPL加載時它不會運行,但如果我直接編譯到我的dUnit exe中,它會運行。 有任何想法嗎? Delphi2005。
達里安提醒我, 我之前已經回答過 :
如果操作系統在加載關聯的EXE時加載BPL,則不會調用所有初始化部分。 相反,只調用程序中其他東西顯式使用的單元中的部分。
如果初始化部分中的代碼注冊了一個類,然后您只是間接引用該類,比如通過在列表中按名稱查找它,那么可能不會調用該單元的初始化部分。 將該單元添加到程序中的任何“uses”子句應該可以解決該問題。
若要解決此問題,您可以通過在SysUtils單元中調用
InitializePackage
函數來自己初始化程序包的單位。 它需要一個模塊句柄,您可以通過調用GetModuleHandle
API函數獲得該句柄。 該函數只調用尚未初始化的單元的初始化部分。 無論如何,這是我的觀察。如果您調用
InitializePackage
,那么您還應該調用FinalizePackage
。 當您的包被卸載時,將為所有自動初始化的單元調用終結部分。如果操作系統沒有自動加載您的軟件包,那么您將使用
LoadPackage
函數加載它。 它會為您初始化所有包的單位,因此您無需自己調用InitializePackage
。 同樣,UnloadPackage
將為您完成所有事情。
只在Quality Central中找到了一個參考,但可能還有更多。 包括LoadPackage引用的解決方法。
在某些情況下,並非BPL中的每個單元都必須初始化。 如果我不得不猜測,我會說這個BPL在加載時鏈接到你的程序而不是以后動態加載? 嘗試將您正在使用的單位的名稱放入DPR中的程序使用列表中。 那應該解決它。
你是如何加載bpl的? 您是否將它留給Delphi進行加載或是否手動加載bpl? 如果您手動加載bpl,是將它作為“直接”dll加載,還是使用LoadPackage將其加載為delphi包? 我認為要么讓vcl加載它(通過需要處理)或使用LoadPackage,初始化部分需要由vcl運行...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.