gpt4 book ai didi

delphi - 在调用 ExitProcess 后,如何判断我是否在 DLL_PROCESS_DETACH 期间被调用?

转载 作者:行者123 更新时间:2023-12-03 15:22:27 24 4
gpt4 key购买 nike

我在 Delphi 中有一个单元(可以选择)提供单个全局对象:

var
InternalThemeParkServices: TThemeParkServices;

function ThemeParkServices: TThemeParkServices;
begin
if InternalThemeParkServices= nil then
InternalThemeParkServices := TThemeParkServices.Create();
Result := InternalThemeParkServices ;
end;

...

initialization
finalization
FreeAndNil(InternalThemeServices);
end.

我在进程关闭期间毁了自己。

Note: Another code variant is:

var
InternalThemeParkServices: IThemeParkServices;

function ThemeParkServices: TThemeParkServices;
begin
if InternalThemeParkServices= nil then
InternalThemeParkServices := TThemeParkServices.Create();
Result := InternalThemeParkServices ;
end;

Where the interface variable is implicitly destroyed when it's reference count goes to zero during program shutdown

当我的对象不再使用时(即在其析构函数期间),我调用各种 WinAPI 函数。

问题是,如果有人从 DLL 中使用我的类(我无法控制的东西),那么在此期间将调用任何内容:

finalization

在德尔福道德中相当于 DLL_PROCESS_DETACHThereall kinds of thingsshould not be doing during DLL_PROCESS_DETACH when the process is terminating (例如CoCreateInstance)。

我知道 Embarcadero 使用:

initialization 
if not IsLibrary then
begin
...

我也许可以适应,改变我的代码:

var
InternalThemeParkServices: IThemeParkServices;

(使用隐式清理),至:

var
InternalThemeParkServices: IThemeParkServices;
...
finalization
if IsLibrary then
Pointer(InternalThemeParkServices) := nil; //defeat reference counting and let the object leak
end;

并让它泄漏。

但这就是最好的解决方案吗?我假设这意味着如果运行我的代码的 dll 被卸载(但不是在进程关闭期间),我将泄漏内存。如果附加和分离 dll,每次都会泄漏。

真正想要的是Delphi在ExitProcess/DllMain(之前运行其finalization block DLL_PROCESS_DETACH)。这可能吗?

奖金闲聊

@pa破译the Delphi application shutdown scheme :

The hierarchy of shutdown is as follows

  Application.Terminate()
performs some unidentified housekeeping of application
calls Halt()

Halt()
calls ExitProc if set
alerts the user in case of runtime error
get rid of PackageLoad call contexts that might be pending
finalize all units
clear all exception handlers
call ExitprocessProc if set
and finally, call ExitProcess() from 'kernel32.dll'

ExitProcess()
unloads all DLLs
uses TerminateProcess() to kill the process

在调用 ExitProcess 之后,DLL 被卸载 - 因为 Windows 是执行此操作的人。

最佳答案

要判断调用 ExitProcess 后是否在 DLL_PROCESS_DETACH 期间调用您,您可以为库编写初始化代码,以便在从主程序调用 FreeLibrary 时执行您的代码。如果已经调用了ExitProcess,则“lpReserved”参数将为“1”,否则为“0”:

..
var
SaveDllProcEx: TDllProcEx;

procedure DllMainEx(Reason: Integer; Reserved: Integer);
begin
if (Reason = DLL_PROCESS_DETACH) and (Reserved = 0) then
// Main app is still running, cleanup.

if Assigned(SaveDllProcEx) then
SaveDllProcEx(Reason, Reserved);
end;

initialization

if IsLibrary then begin
SaveDllProcEx := DllProcEx;
DllProcEx := @DllMainEx;
end;


来自 DllMain entry point :

The lpReserved parameter indicates whether the DLL is being unloaded as a result of a FreeLibrary call, a failure to load, or process termination.

关于delphi - 在调用 ExitProcess 后,如何判断我是否在 DLL_PROCESS_DETACH 期间被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10353417/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com