Board index » delphi » DllProc versus initialization/finalization

DllProc versus initialization/finalization

Hi. I have quetions regarding to a dll which is loaded by multiple
processes.

Consider two pieces of code

1. (in .dpr of a library)

...
procedure LibraryProc(Reason: Integer);
begin
  case Reason of
    DLL_PROCESS_ATTACH: InitMyGlobalHandles; // Dll global data
initialization;
    DLL_PROCESS_DETACH: FreeMyGlobalHandles; // Dll global data
finalization;
  end;
end;

begin
  DllProc := LibraryProc;
  LibraryProc(DLL_PROCESS_ATTACH);
end.

2. (in unit of a library)

....

initialization
  InitMyGlobalHandles; // Dll global data initialization;
finalization
  FreeMyGlobalHandles;
end.

The questions is:

Does it make diference between 1. and 2. ? I mean is there any case when
code 1. executes InitMyGlobalHandles and code 2. not (or vice versa) ?

Can I assert that InitMyGlobalHandles will never be called more than once
for the same global variable ?

Thanks in advance.

 

Re:DllProc versus initialization/finalization


Quote
"GuAV" <format('%s@'+'%s.%s', ['guav','mail','ru'])> wrote in message

news:41d418e6@newsgroups.borland.com...
...

Quote
> 1.
> begin
>   DllProc := LibraryProc;
>   LibraryProc(DLL_PROCESS_ATTACH);
> end.

> 2. (in unit of a library)
> initialization
>   InitMyGlobalHandles; // Dll global data initialization;
> finalization
>   FreeMyGlobalHandles;
> end.

> Does it make diference between 1. and 2. ? I mean is there any case when
> code 1. executes InitMyGlobalHandles and code 2. not (or vice versa) ?

> Can I assert that InitMyGlobalHandles will never be called more than once
> for the same global variable ?

Yes. Both versions of your code will always run, but there is still a
difference as in when exactly this happens. The begin ... end. block in the
.dpr is the last thing that gets executed after everything is loaded and all
units are initialized. LibraryProc will also get the finalization message
first, while none of the other units are yet finalized. If you use the
init/final section of a unit instead (2), delphi will make sure that it
initializes in the correct order of dependencies.

This means, you can sefely use this unit by other units and in their init
sections assume that it is already initialized and when your unit is
finalized, you can safely assume that all units that depend on it have
already been finalized. Of course, this can fail if your units have circular
references to each other (in the implementation section), in this case the
initialization order is determined by the order your units appear in the
project and/or are used by other units. If however you do not use circular
references, you can rely on the initialization and finalization order being
correct.

In the first case (LibraryProc in .dpr) you have to make sure that you start
up and shut down everything in the correct order and you cannot use anything
from your globals' unit in the init/final sections of any other units.
Furthermore there can only exist one LibraryProc in a dll while the
init/final section can exist in multiple units whenever necessary.

In both cases your global init routine is run exactly once, it will never
called twice per process and also never missed. The second approach is the
safer and more convenient one since the RTL handles everything in the
correct order and you can program it just like in a 'normal' application
except of course using IPC during initialization and finalization.

There is however a case when you need to use the first approach: That one is
required when you need to trap DLL_THREAD_ATTACH (/DETACH) messages to deal
with the thread-local storage (TLS) and to use delayed synchronization (you
do not allocate and/or use sync objects until the app that uses your dll
spawns its first non-primary thread thus making your dll work faster with
singlie-threaded apps). If you intend to optimize your dll in this way,
please remember that when a dll gets loaded dynamically via LoadLibrary it
is only notified about being attached to a process. If the process has
already started several threads by this time, the dll does not get the
thread-attach messages for them. For this reason you have to enumerate all
threads in your process on dll startup, check here whether more than one
already exists and handle the sync stuff accordingly. Even in this case I
would recommend to use unit's init/final sections for the general
initialization and use the LibraryProc only for TLS and/or delayed sync
initialization.

I hope this helps,

Dimitrij

Re:DllProc versus initialization/finalization


Very helpful. Thank You.

Other Threads