Delphi 单元初始化顺序与源代码中的指示不符

Delphi 单元初始化顺序与源代码中的指示不符,delphi,delphi-xe4,Delphi,Delphi Xe4,我有一个项目,其中多个单元有初始化部分。我想控制执行这些块的顺序 根据以下内容,这是基于单元的编译顺序,因此最终顺序应基于源DPR的uses子句中的单元安排 以下是我项目的DPR来源: program X; uses Vcl.Forms, uMain in 'uMain.pas' {MainForm}, uFooA in 'uFooA.pas', uFooB in 'uFooB.pas'; {$R *.res} begin Application.Initialize;

我有一个项目,其中多个单元有初始化部分。我想控制执行这些块的顺序

根据以下内容,这是基于单元的编译顺序,因此最终顺序应基于源DPR的uses子句中的单元安排

以下是我项目的DPR来源:

program X;

uses
  Vcl.Forms,
  uMain in 'uMain.pas' {MainForm},
  uFooA in 'uFooA.pas',
  uFooB in 'uFooB.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;

end.
我的问题是,这根本不是执行初始化块的顺序

How it should be |  How it actually is
                 | 
  1. uMain       |     1.uFooA
  2. uFooA       |     2.uFooB  
  3. uFooB       |     3.uMain
我很想提供一个SSCCE,但我无法在一个新的项目上重新制作这个问题

我试图重建这个项目,但没有成功


我遗漏了什么?

尽管编译器有一种严格的方式来确定初始化,但对于一个人来说,当有许多具有许多依赖关系的单元时,很难准确地判断和控制

例如,您的DPR可以使用
UnitA、UnitB、UnitC但如果
UnitA
依赖于
UnitB
,则必须首先初始化UnitB

诚然,具有初始化终结部分的单元的特性可以使添加功能变得像“添加单元”一样简单。虽然这看起来很好,但实际上,在真正大型的项目中,它往往会成为阻碍。就我个人而言,我认为“特征”相当可怕。 控制机组优化顺序的最佳和最可靠的方法是明确地这样做。例如

program X;

uses
  Vcl.Forms,
  uMain in 'uMain.pas' {MainForm},
  uFooA in 'uFooA.pas',
  uFooB in 'uFooB.pas';

{$R *.res}

begin
  Init_uMain;
  Init_uFooA;
  Init_uFooB;

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;

  Finalise_uFooB;
  Finalise_uFooA;
  Finalise_uMain;
end.

显然,上面的代码缺少适当的try..finallys,并且会因为许多单元需要初始化而变得混乱。然而,还有其他技术可以用来保持事情的可管理性。

uMain是否使用uFooA和/或uFooB?在这种情况下,使用的单位首先被编译。@Uwerabe,啊,是的,它们是,愚蠢的我。。。请发布一个答案,以便我可以接受。我不确定这里是否需要答案。Mason在你链接到的答案中的解释说明了一切:编译器从DPR的uses子句的顶部开始向下运行,对于找到的每个单元,它递归地执行相同的操作:从uses子句的开头开始,尝试编译每个未编译的已用单元,然后编译当前单元。因此,如果您能在编译其他任何单元之前将单元导入,那么它将首先初始化。@DavidHeffernan,感谢您指出这一点,我已经阅读了它,但我跳过了最重要的部分:s