Delphi并在一个单元中完成

pKa*_*ian 4 delphi finalization

我有两个单位unitA和unitB.类TFoo在unitB中声明.

在单元A的最终确定中调用B.Free是否总是安全的?

它如何依赖于unitA和unitB在dpr中的顺序?

执行unitA终结时,我能确定unitB是否存在?

unit unitB;
interface
type
 TFoo = class
   // code...
  end;
 // code....
end;

unit unitA;
// code..
implementation
uses
 unitB;
var
 A: TStringList;
 B: UnitB.TFoo;

initialization
 A:= TStringList.Create;
 B:= UnitB.TFoo.Create;
finalization
 A.Free;
 B.Free;  // Is it safe to call?
end.
Run Code Online (Sandbox Code Playgroud)

Jim*_*eth 16

是的,你应该没问题,因为B是在单元A中创建的.规则是初始化部分是根据它们在DPR中的顺序调用的,除非其中一个单元引用另一个单元.在这种情况下,首先初始化引用的单元.最终确定顺序相反.

在你的情况下,单元B没有初始化部分,所以这是一个有争议的问题.但是,当执行单元A初始化部分时,它将使用单元B中的TFoo定义.

关于Initialization和Finalization部分的另一个警告 - 它们发生在全局异常处理程序之外.发生的任何异常都会终止应用程序.因此,跟踪和调试这些异常可能是大型程序的痛苦.您可以考虑在那里使用自己的异常日志记录,以确保.

  • 投票赞成"全球例外处理程序"说明 (2认同)

DiG*_*iGi 5

不。你可以尝试,你可以希望,但不能保证调用初始化和终结的顺序。参阅qc72245qc56034等。

更新:

  1. 终结部分以与初始化相反的顺序执行。您的示例是安全的,您不依赖于在单元之间调用初始化部分
  2. Delphi可以混合调用单元(第1点仍然有效,初始化和终结部分都交换了)

例子:

unitA // no dependency on unitB
var SomeController;
initialization
  SomeController := TSomeController.Create;
finalization
  SomeController.Free;

unitB
uses
  unitA;
initialization
  SomeController.AddComponent(UnitBClass);
finalization
  SomeController.RemoveComponent(UnitBClass);
Run Code Online (Sandbox Code Playgroud)

常见(正确)调用顺序(99.99%):

  1. 单元A.初始化
  2. 单元B.初始化
  3. 跑步...
  4. 单元B.最终确定
  5. 单元A.最终确定

有时Delphi编译文件会出错:

  1. unitB.initialization - AV 这里
  2. 单元A.初始化
  3. 跑步...
  4. 单元A.最终确定
  5. unitB.finalization - 也在这里

题外话小故事:

我们有一个相当大的项目,Unit1中有Type1,Unit2中有Type2 = class(Type1)。文件在project.dpr中排序,并在几年后添加Unit200(与unit1/2没有依赖性)Delphi开始在Unit1.Initialization之前使用Unit2.Initialization编译项目。唯一安全的解决方案是从初始化部分调用您自己的 Init 函数。

  • 但这取决于情况。**最终化**部分**以与初始化相反的顺序执行,但 Delphi 可以交换单位和顺序 (2认同)