单元确定订单的应用程序,使用运行时包编译? [英] Unit finalization order for application, compiled with run-time packages?

查看:145
本文介绍了单元确定订单的应用程序,使用运行时包编译?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我将代码放在单独的单元中,并将其首先包含在dpr文件的uses子句中,如下所示:

  project Project1; 

使用
MyUnit,//< - 我的单独单元
SysUtils,
类,
SomeOtherUnits;

程序测试;
begin
//
end;

begin
SetProc(Test);
结束。

MyUnit如下所示:

  unit MyUnit; 

界面

程序SetProc(AProc:TProcedure);

实现

var
测试:TProcedure;

程序SetProc(AProc:TProcedure);
begin
测试:= AProc;
结束

初始化

finalization
测试;
结束。

请注意,MyUnit没有任何用处。



这是通常的Windows exe,没有控制台,没有表单,并使用默认的运行时包进行编译。 MyUnit不是任何包的一部分(但我也试图从包中使用它)。



我希望MyUnit的定稿部分将被执行SysUtils的完成部分。这是Delphi的帮助告诉我的。



但是,并不总是这样。



我有2测试应用程序,在使用中列出的Test routine / dpr文件和单元中的代码有所不同。然而,MyUnit在所有情况下都是首先列出的。



一个应用程序按预期运行: Halt0 - > FinalizeUnits - > ...其他单元... - > SysUtils的完成 - > MyUnit的完成 - >。 ..其他单位...



但第二个不是。 MyUnit的最终确定在 SysUtils的最终确定之前被调用。实际的电话链如下所示: Halt0 - > FinalizeUnits - > ...其他单位... - > SysUtils的最终确定(跳过) - > MyUnit的最终确定 - > ...其他单位... - > SysUtils的最终确定(执行)



两个项目都有非常相似的设置。我尝试删除/最小化他们的差异,但我仍然没有看到这个行为的原因。



我试图调试这个,发现:看来每个单位都有某种参考计数。而且,似乎InitTable包含对相同单元的乘法引用。当SysUtils的最终确定部分被称为第一次 - 它会改变引用计数器,什么都不做。然后执行MyUnit的完成。然后SysUtils再次被调用,但这次ref-count达到零并执行完成部分:

  Finalization:// SysUtils 'finalization 
5003B3F0 55 push ebp //这里和下面是一些形式的存根
5003B3F1 8BEC mov ebp,esp
5003B3F3 33C0 xor eax,eax
5003B3F5 55 push ebp
5003B3F6 688EB50350 push $ 5003b58e
5003B3FB 64FF30 push dword ptr fs:[eax]
5003B3FE 648920 mov fs:[eax],esp
5003B401 FF05DCAD1150 inc dword ptr [$ 5011addc] //这里:某种参考计数器
5003B407 0F8573010000 jnz $ 5003b580 //< - 此跳过跳过执行第一次调用的完成
5003B40D B8CC4D0350 mov eax,$ 50034dcc //这里和下面是实际的SysUtils'最终确定部分
...

任何人都可以在这个问题上闪光?我错过了什么吗?

解决方案

我找到了一个理由,现在觉得自己有点傻了:)



我的第二个测试应用程序具有静态引用到DLL,它是用RTL.bpl编译的(它是空的,除了引用SysUtils并有1个简单例程)。所以,由于DLL是静态链接的,所以在exe有任何代码有机会运行之前被初始化。



就是这样:



DLL的系统 - > DLL的 SysUtils - > exe的系统(跳过) - > MyUnit exe的 SysUtils (跳过) - > etc



结束语是相反的顺序,导致在SysUtils之前执行MyUnit。



解决方案:需要在所有项目中首先包含MyUnit。



(哦,我希望有一台时间机器回来及时强制有人添加OnBeforeMMShutdown事件:D)


I need to execute my code after finalization of SysUtils unit.

I've placed my code in separate unit and included it first in uses clause of dpr-file, like this:

project Project1;

uses
  MyUnit,    // <- my separate unit
  SysUtils,
  Classes,
  SomeOtherUnits;

procedure Test;
begin
  //
end;

begin
  SetProc(Test);
end.

MyUnit looks like this:

unit MyUnit;

interface

procedure SetProc(AProc: TProcedure);

implementation

var
  Test: TProcedure;

procedure SetProc(AProc: TProcedure);
begin
  Test := AProc;
end;

initialization

finalization
  Test;
end.

Note that MyUnit doesn't have any uses.

This is usual Windows exe, no console, without forms and compiled with default run-time packages. MyUnit is not part of any package (but I've tried to use it from package too).

I expect that finalization section of MyUnit will be executed after finalization section of SysUtils. This is what Delphi's help tells me.

However, this is not always the case.

I have 2 test apps, which differs a bit by code in Test routine/dpr-file and units, listed in uses. MyUnit, however, is listed first in all cases.

One application is run as expected: Halt0 -> FinalizeUnits -> ...other units... -> SysUtils's finalization -> MyUnit's finalization -> ...other units...

But the second is not. MyUnit's finalization is invoked before SysUtils's finalization. The actual call chain looks like this: Halt0 -> FinalizeUnits -> ...other units... -> SysUtils's finalization (skipped) -> MyUnit's finalization -> ...other units... -> SysUtils's finalization (executed)

Both projects have very similar settings. I tried a lot to remove/minimize their differences, but I still do not see a reason for this behaviour.

I've tried to debug this and found out that: it seems that every unit have some kind of reference counting. And it seems that InitTable contains multiply references to the same unit. When SysUtils's finalization section is called first time - it change reference counter and do nothing. Then MyUnit's finalization is executed. And then SysUtils is called again, but this time ref-count reaches zero and finalization section is executed:

Finalization: // SysUtils' finalization
5003B3F0 55               push ebp          // here and below is some form of stub
5003B3F1 8BEC             mov ebp,esp
5003B3F3 33C0             xor eax,eax
5003B3F5 55               push ebp
5003B3F6 688EB50350       push $5003b58e
5003B3FB 64FF30           push dword ptr fs:[eax]
5003B3FE 648920           mov fs:[eax],esp
5003B401 FF05DCAD1150     inc dword ptr [$5011addc] // here: some sort of reference counter
5003B407 0F8573010000     jnz $5003b580     // <- this jump skips execution of finalization for first call
5003B40D B8CC4D0350       mov eax,$50034dcc // here and below is actual SysUtils' finalization section
...

Can anyone can shred light on this issue? Am I missing something?

解决方案

I was able to find a reason and I feel myself a bit stupid now :)

My second test application have a static reference to DLL, which was compiled with RTL.bpl (it's empty, except for references to SysUtils and having 1 simple routine). So, since DLL is statically linked, it is initialized before any code from exe have chances to run.

That's it:

DLL's System -> DLL's SysUtils -> exe's System (skipped) -> MyUnit -> exe's SysUtils (skipped) -> etc

Finalizations are in reverse order, leading to execution of MyUnit before SysUtils.

Solution: require to include MyUnit first in all projects.

(oh, how I wish to have a time-machine to travel back in time and force somebody to add OnBeforeMMShutdown event :D )

这篇关于单元确定订单的应用程序,使用运行时包编译?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆