finalization ShowMessage('Goodbye'); end.
关闭Delphi会显示消息,但不会在我的应用程序关闭时显示.如果我在ShowMessage上设置一个断点,它会在那里中断,但不执行该行,这更令人讨厌.如果最终化中有多行,则调试器在第一行停止,不执行它然后跳转到结尾.
procedure ProcOne; begin SomeObject.Free; // Debugger does not enter or stop here SomeObject := nil; end; finalization ProcOne; // Debugger stops here,doesn't execute,jumps to "end." ProcTwo; // Every line has a blue dot ShowMessage('Bye'); end.
ProcOne断点上的调用堆栈显示@ Halt0 => FinalizeUnits => MyPackage.MyUnit.Finalization.
如果我将该单元包含在不使用包的应用程序中,则一切都正常执行.
有谁知道可能导致这种情况的原因是什么?
编辑:
感谢Allen Bauer的评论指向了正确的方向,我已经设法解决了这个问题.如果使用运行时包构建应用程序,然后动态加载另一个也引用该包和单元的包,则似乎会出现问题.
我创建了一个演示问题的测试项目:TestFinalization
有谁知道这个和/或解决方法的原因?在您注意到外部资源未被清除之前,您通常可能不会注意到您的终结未运行.
解决方法
使用编译器生成的表为给定模块完成初始化/完成.当您构建与包链接的exe或dll时,此表包含对实际使用的所有单元的引用,甚至包括来自链接包的那些单元.请注意,实际上仅实际引用的单元已初始化. IOW,如果您在PackageA中有100个单位且exe只引用其中一个单位,则只会初始化该单位及其使用的任何单位.
对于动态加载的包,实际上无法知道实际使用哪些单元,因此编译器会生成init / finit表,就好像每个单元都已初始化一样.在调用LoadLibrary期间加载包时不处理此表,而是通过调用名为Initialize()的特殊导出来处理. LoadPackage函数确保调用此函数.此表仅确保初始化加载包中的所有单元.初始化只有实际触及任何其他包的单元,类似于我上面提到的exe / dll情况. UnloadPackge执行相反的操作,并在调用UnloadLibrary()之前调用特殊导出Finalize().
最后,如果您对使用任何打包单元的列表进行了更改并且仅重建了包,则可能会遇到令人困惑的情况,即使给定包中的单元正确地“相互使用”,也可能无法调用初始化/终结.这是因为init / finit由加载模块控制而不是从其自身内部控制.仅在使用LoadPackage显式加载包的情况下,才会初始化/最终确定该包中的每个单元(以及该包).
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。