问题描述
我在 .bpl 中有一个单元,我需要一个字符串列表用于我编写的新函数.我希望字符串列表在应用程序的整个生命周期内保持不变,以便每次调用都可以建立在先前调用找到的内容之上.
I have a unit within a .bpl, and I need a stringlist for a new function that I wrote. I want to the stringlist to persist for the lifetime of the app, so that each call can build on what the prior call found.
所以它在单元内全局声明,我在初始化部分对其进行初始化,如下所示:
So it's declared globally within the unit, and I initialize it in the Initialization section, like this:
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.
当我对它进行单元测试时,一切都很好.但是当它从主应用程序运行时,我因访问冲突而崩溃,因为字符串列表为 nil.所以现在我求助于检查 foo 函数中的 nil 并在必要时创建.但是我不知道为什么初始化对我不起作用.我在初始化中放了一条调试消息,当它作为 BPL 加载时它不会运行,但是如果我直接编译到我的 dUnit exe 中就会运行.有任何想法吗?Delphi2005.
When I unit tested it, everything was fine. But when it gets run from the main app, I was blowing up with an access violation because the stringlist was nil. So now I'm resorting to checking for nil in the foo function and creating if necessary. But I'm at a loss as to why the initialization isn't working for me. I put a debug message right there in the Initialization, and it doesn't get run when this loads as a BPL, but DOES get run if I compile directly into my dUnit exe. Any ideas? Delphi2005.
推荐答案
Darian 提醒我 我之前回答过这个问题:
Darian reminds me that I've answered this before:
如果操作系统将 BPL 作为加载相关 EXE 的一部分加载,则并非所有初始化部分都会被调用.相反,只有那些被程序中的其他东西明确使用的单元中的部分才会被调用.
如果初始化部分中的代码注册了一个类,然后您只是间接引用该类,例如通过在列表中按名称查找它,那么单元的初始化部分可能不会被调用.将该单位添加到任何用途"中.程序中的子句应该可以解决这个问题.
If the code in the initialization section registers a class, and then you only refer to that class indirectly, say by looking for it by name in a list, then the unit's initialization section might not get called. Adding that unit to any "uses" clause in your program should solve that problem.
要解决此问题,您可以通过调用 InitializePackage
函数,在 SysUtils 单元中.它需要一个模块句柄,您可以通过调用 GetModuleHandle代码>
API 函数.该函数只会调用尚未初始化的单元的初始化部分.无论如何,这是我的观察.
To work around this problem, you can initialize the package's units yourself by calling the InitializePackage
function, in the SysUtils unit. It requires a module handle, which you can get by calling the GetModuleHandle
API function. That function will only call the initialization sections of the units that haven't already been initialized. That's my observation, anyway.
如果你调用InitializePackage
,那么你也应该调用FinalizePackage
.当你的包被卸载时,将调用所有自动初始化的单元的终结部分.
If you call InitializePackage
, then you should also call FinalizePackage
. When your package gets unloaded, the finalization sections will get called for all the units that were automatically initialized.
如果操作系统不自动加载你的包,那么你正在使用 LoadPackage
函数加载它.它会为您初始化所有包的单元,因此您无需自己调用 InitializePackage
.同样,UnloadPackage
将为您完成所有工作.
If the OS does not automatically load your package, then you are loading it with the LoadPackage
function. It initializes all the package's units for you, so you don't need to call InitializePackage
yourself. Likewise, UnloadPackage
will finalize everything for you.
这篇关于Delphi 单元初始化并不总是被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!