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?
Units are finalized in reverse order of initialization. The order of initialization is determined by a non-cyclic (i.e. never descends into an already-visited unit) post-order traversal of the unit uses graph, starting with the main uses clause (in the program or library). SysInit is normally the first unit to be initialized, followed by System.
Dynamic loading of packages complicates things, because the main EXE or DLL gets to specify the order of initialization of the units used by the main image. So when a package is dynamically loaded, it will run what it thinks should be the initialization order, but units already initialized will be skipped; when the package is dynamically unloaded, this happens in reverse.
The general rules:
lower-level things should be initialized before higher-level things
finalization should be in reverse order of initialization
These rules almost always make sense. Higher-level units' initializations often rely on services provided by lower-level units. For example, without SysUtils, there is no exception support in Delphi. Reverse order finalization makes sense for the same reason: high-level finalizations rely on services provided by lower-level units, so they must run before the lower-level units' finalizations.
All that said, with respect to your problem, it sounds like there may be a bug somewhere in the compiler or RTL, if what you say is true: that the main EXE uses MyUnit first, and MyUnit uses no other units in its interface or implementation, and there's no funny business going on with dynamically loaded packages. All I can suggest is to keep paring down the project with the odd behaviour until you have a minimal reproducing sample; at that point, it should be clear exactly what is causing the problem.
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 )
You're not missing anything. That's exactly what's happening.
When your program loads a package, it will initialize all the units used in that package. When it unloads the package, it has to finalize all the units. But finalization often involves freeing variables. Remember that double-frees are a Bad Thing, especially if they happen during finalization when certain exception-handling features might have been unloaded, making debugging very difficult. So it puts a reference counter on the unit initializations so that they don't get finalized until everything that was using them is done with them.
Is there any particular reason why your MyUnit needs to finalize after SysUtils?
I am not sure but isn't there still the good old ExitProc global variable of Turbo/BorlandPascal fame? If yes, this could solve your problem.
Related
I have an application which load a DLL that makes use of Delphi GDI+ Library. This application hangs when it unload the DLL (Calling FreeLibrary).
I tracked the issue down to GdiPlus.pas unit finalization section which calls GdiPlusShutdown which never returns.
How to avoid this deadlock?
The documentation for the GdiplusStartup function says this:
Do not call GdiplusStartup or GdiplusShutdown in DllMain or in any
function that is called by DllMain. If you want to create a DLL that
uses GDI+, you should use one of the following techniques to
initialize GDI+:
Require your clients to call GdiplusStartup before they call the functions in your DLL and to call GdiplusShutdown when they have
finished using your DLL.
Export your own startup function that calls GdiplusStartup and your own shutdown function that calls GdiplusShutdown. Require your clients
to call your startup function before they call other functions in your
DLL and to call your shutdown function when they have finished using
your DLL.
Call GdiplusStartup and GdiplusShutdown in each of your functions that make GDI+ calls.
By compiling this Delphi GdiPlus library into a DLL you are breaking this rule for both GdiplusStartup and GdiplusShutdown. These functions are called in unit initialization and finalization sections, respectively. And for library projects, code in the initialization and finalization sections of a unit is executed from DllMain.
It seems that the GdiPlus library that you use was never intended to be used from a library. But as a general rule, when writing library code, you should be aware of the restrictions around DllMain and make sure that code that you place in initialization and finalization sections respects that. I think that this GdiPlus library fails in that regard.
By way of contrast, have a look at the code in the Delphi RTL's WinApi.GDIPOBJ unit:
initialization
if not IsLibrary then
begin
// Initialize StartupInput structure
StartupInput.DebugEventCallback := nil;
StartupInput.SuppressBackgroundThread := False;
StartupInput.SuppressExternalCodecs := False;
StartupInput.GdiplusVersion := 1;
GdiplusStartup(gdiplusToken, #StartupInput, nil);
end;
finalization
if not IsLibrary then
begin
if Assigned(GenericSansSerifFontFamily) then
GenericSansSerifFontFamily.Free;
if Assigned(GenericSerifFontFamily) then
GenericSerifFontFamily.Free;
if Assigned(GenericMonospaceFontFamily) then
GenericMonospaceFontFamily.Free;
if Assigned(GenericTypographicStringFormatBuffer) then
GenericTypographicStringFormatBuffer.free;
if Assigned(GenericDefaultStringFormatBuffer) then
GenericDefaultStringFormatBuffer.Free;
GdiplusShutdown(gdiplusToken);
end;
This code respects the rules by making sure that it does not call GdiplusStartup and GdiplusShutdown from DllMain. Instead it leaves the onus on the author of any library that uses WinApi.GDIPOBJ to make sure that GdiplusStartup and GdiplusShutdown are called at appropriate times.
If I were you I would pick one of the three bullet point options listed above. The third of these options is not very practical, but the first two are good choices. Were it me, I would opt for the first option and modify the initialization and finalization code in your GdiPlus library to look more like that found in WinApi.GDIPOBJ.
GdiPlusShutdown (and GdiPlusStartup btw) cannot be called from DllMain but DllMain is called by Windows and Delphi runtime when FreeLibrary is called: Delphi call the finalization section of all units used by the DLL and GdiPlus finalization section calls GdiPlusShutdown (This is perfectly OK when used from an executable). Similar behavior with initialization section.
I have fixed the issue by adding a test for IsLibrary in both initialization and finalization sections to avoid calling the offending functions, also added two public procedures InitializeForDll and FinalizeForDll. With those little changes, the DLL is able to export functions calling InitializeForDll and FinalizeForDll. Those exported function have to be called by the hosting application right after loading the DLL and just before unloading the DLL.
Here are the changes I made to GdiPlus.pas:
In the interface section:
var
procedure InitializeForDll;
procedure FinalizeForDll;
In the implementation section:
procedure InitializeForDll;
begin
Initialize;
end;
procedure FinalizeForDll;
begin
Finalize;
end;
Also updated the initialization and finalization sections like this:
Initialization
if not IsLibrary then
Initialize;
Finalization
if not IsLibrary then
Finalize;
In the DLL, I exported those functions:
procedure Initialize; stdcall;
begin
GdiPlus.InitializeForDll;
end;
procedure Finalize; stdcall;
begin
GdiPlus.FinalizeForDll;
end;
Initialize and Finalize are called by the hosting application right after calling LoadLibrary and just before calling FreeLibrary (Or whatever will load/unload the DLL).
I hope this will help others.
btw: Thanks to Eric Bilsen for providing Delphi GdiPlus Library
I use Delphi's LeakCheck library https://bitbucket.org/shadow_cs/delphi-leakcheck.
I know I can disable leak reporting using a construct like this:
{$IFDEF DEBUG}
System.ReportMemoryLeaksOnShutdown := true; // this will enable LeakCheck to display a message on Windows
{$ELSE}
System.ReportMemoryLeaksOnShutdown := false;
{$ENDIF}
But I also need the library to NOT collect any data when compiled in RELEASE mode.
I can easily "hack" the LeakCheck.pas initialization/finalization sections like this:
...
{$IFDEF DEBUG} // <--- Code added by me
initialization
TLeakCheck.Initialize;
finalization
TLeakCheck.Finalize;
{$ENDIF} // <--- Code added by me
end.
Is there any better way? A conditional define I miss or a global property?
I don't use the specific library (LeakCheck) you mention, but I typically do this by only including the unit when the right configuration is defined (in this case, DEBUG). This means that in release it's not even included in the executable.
uses
...,
{$IFDEF Debug}
LeakCheck,
{$ENDIF}
...;
As is pointed out in a comment, LeakCheck has to be the first unit listed in the .dpr's uses clause, which may cause an occasional problem with the IDE; it sometimes ends up breaking due to the {$IFDEF}. I usually don't find this to be a major issue, because once it happens and you've seen what the cause is, it's pretty easy to just go back in and fix it.
If that becomes too much of an issue, there is another workaround - create a new unit that does nothing but use LeakCheck and SysUtils, and add the above {$IFDEF} in that unit. You then include the new unit first in your .dpr. As it's only task is actually to use LeakCheck, it still puts LeakCheck in first-compile order in the .dpr when needed, and does not include it at all when not.
I am running a ISAPI service which runs with IdHTTPWebBrokerBridge (for debugging as standalone EXE) as well as in Apache with mod_isapi (in productive enviroment).
While logging some stuff at the destruction of the web module, I found following problem:
unit LogFactory;
...
initialization
GlobalLogFactory := TMyLogFactory.Create;
finalization
FreeAndNil(GlobalLogFactory);
end.
-
unit MyWebModuleUnit;
...
uses LogFactory;
procedure TMyWebModule.WebModuleDestroy(Sender: TObject);
begin
Assert(Assigned(GlobalLogFactory)); // <-- failure
GlobalLogFactory.GetLogger('D:\test.txt').LogLine('test'); // <-- Nullpointer Exception
end;
LogFactory.pas creates the object GlobalLogFactory on its initialization and destroys it on its finalization.
But LogFactory.pas:finalization gets called BEFORE TMyWebModule.WebModuleDestroy , since it was included by this unit only, and so the finalization will be done in reverse order.
How can I ensure that my GlobalLogFactory will be correctly freed (i.e. FastMM will not warn about a memory leak), but at the same time, I want to give all destruction/finalization-procedures the chance to log something?
One Workaround would be to include LogFactory.pas explicitely in the DPR file as the first unit. But I don't like that very much, since this Log-Unit should be used in many projects and it should be useable by simply including it in the unit where you need to log something. Putting this log unit in every DPR which might want to log something in future, is a big effort and forgetting it might cause problems for the developers who are not knowing what I did/require.
Instad of using a class instance in a global variable use an interface and a function to get that.
unit LogFactory;
interface
type
ILogFactory = interface
[{GUID}]
function GetLogger(...) : TLogger;
...
end;
TLogFactory = class( TInterfacedObject, ILogFactory )
function GetLogger(...) : TLogger;
end;
function GlobalLogFactory : ILogFactory;
implementation
var
_LogFactory : ILogFactory;
function GlobalLogFactory : ILogFactory;
begin
if not Assigned( _LogFactory ) then
_LogFactory := TLogFactory.Create;
Result := _LogFactory;
end;
{ TLogFactory Implementation }
initialization
// nothing needed
finalization
// nothing needed
end.
There is no need for any initialization or finalization at all.
If you want
Any unit in your program to be able to log, and
Logging to be available during finalization, and
The logging code to require tidy up,
then you don't have many options. One option is to include the log unit very early in the .dpr file. I don't know why you regard that to be a problem. It's the standard way to achieve your goals. It's the technique used by external memory managers for example. Delphi developers are familiar with the concept. You tell the developers what they need to do, and if they don't follow your instructions, the program does not work. That is their problem.
If you still cannot face doing it this way then I see one alternative. Arrange for the logger initialization to happen before any other initialization in your code. And the finalization after all other finalization. You can do that by putting the logger implementation into an external module that is linked with load time linking.
in mine project i have a Windows application and a dll. I have wrote dll so:
library MyDLL;
uses
System.SysUtils,
System.Classes;
{$R *.res}
function Prova: string; export;
begin
result := 'prova';
end;
exports Prova;
begin
end.
and in main program i have called routine so:
unit FrmMain;
interface
uses
// declaration uses //
function Prova: string; external 'MyDLL.dll';
type
// declaration type //
implementation
begin
...
TAdvEdit1.Text := Prova; // [1] //
...
end;
end.
When i compile all project not is reported error, and status report SUCCESS, but application not start.
If i remove the line [1] then it works correctly. In general, application not start when i call the function Prova.
What i can solve this problem? Thanks very much.
The behaviour you describe is what happens when your application fails to load. When run from the debugger you get a silent failure. When run without a debugger you will see an error message, "Application failed to initialize...". This will give details.
In your case it seems that the likely cause is that the dependency of the DLL cannot be resolved by the library loader. That's why the app runs when the call to the external function is removed. When you remove that call, you also remove the dependency on the external DLL. Solve the problem by making sure the DLL can be loaded. For example place it in the same directory as the executable.
The silent failure from the debugger is rather frustrating. Once you have experienced it a few times you'll know what to do - run without the debugger to find out what's really going wrong.
I also recommend that you don't pass managed Delphi strings across module boundaries. That will force you to use the same compiler for both executable and DLL. If you are going to accept that constraint then you may as well use packages. As your code stands, it would need to use ShareMem to work. But I don't recommend that.
Your program and your DLL have separate memory manager. As a general rule memory allocated from DLL should not be used inside your application (the opposite is also true).
Where the allocation comes from? In Delphi "string" is managed type i.e. when you assign some text to a string variable (in your case result := 'prova'), Delphi (behind the scene) allocates memory for that string using DLL's memory manager. Then, for example, if you assign other text value within your main application, the reallocation uses application's memory manager which is bad i.e. app's MM is touching memory that it hasn't allocated itself.
To solve this issue you have to include "SimpleShareMem" (Delphi >= 2010 IIRC?) unit as the first unit of your USES clause in the application (.dpr file) AND in the DLL:
library MyDLL;
uses
SimpleShareMem, // **MUST BE THE FIRST UNIT**
System.SysUtils,
System.Classes;
...
program YourApp;
uses
SimpleShareMem, // **MUST BE THE FIRST UNIT**
// declaration uses //
An example of this approach can be found in "Start > Programs > Embarcadero RAD Studio > Samples > Delphi > RTL > SimpleShareMem"
You can also use PCHAR to transfers strings between DLL and the APP.
I am using Delphi 7 IDE. Does Delphi compiler optimize codes, just like what the C++ compiler is doing in this following link?
http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx
WCHAR szPassword[MAX_PATH];
// Retrieve the password
if (GetPasswordFromUser(szPassword, MAX_PATH))
UsePassword(szPassword);
// Clear the password from memory
SecureZeroMemory(szPassword, sizeof(szPassword));
If ZeroMemory were called in this example instead of SecureZeroMemory, the compiler could optimize the call because the szPassword buffer is not read from before it goes out of scope. The password would remain on the application stack where it could be captured in a crash dump or probed by a malicious application.
Yes, of course Delphi performs optimizations. However, it does not perform the optimization that the SecureZeroMemory function is meant to circumvent. There is no need to use that function in Delphi; just use plain old ZeroMemory, or even FillChar. They're not macros, and they don't do anything that Delphi recognizes as being unused assignment statements that could get optimized out.
Delphi performs code optimization by default, you can disable it in Project > Options > Compiler.
The Delphi help provide a few tips of what type of optimizations are used:
The $O directive controls code optimization. In the {$O+} state, the compiler performs a number of code optimizations, such as placing variables in CPU registers, eliminating common subexpressions, and generating induction variables.
It also states that "the compiler performs no "unsafe" optimizations", but in the sense that they won't alter the execution path, not from a security point of view.
Delphi certainly optimizes code (it is a modern, and excellent, compiler). Another example of optimization deleting lines is:
SomeFunction(); // Set breakpoint here, then step (F10)
myInt := 7; // Next line will not hit this...
myInt := 13; // ...but will instead skip to here
I like to ensure optimization is in the correct state (and not accidentally left switched on or off) by adding {$I MyProjectOptions.inc} in every .pas file in my project. This goes just below the unit name (right at the top of the file). In "MyProjectOptions.inc" you simply add this code:
// Is this a debug or non-debug build?
{$IF Defined(DEBUG)}
{$O-} // Turn optimization off
{$ELSEIF Defined(NDEBUG)}
{$O+} // Ensure optimisation is on
{$IFEND}
Finally, ensure you have defined "DEBUG" and "NDEBUG" (or your equivalent in older versions of Delphi) in the Conditional defines section of Project > Options > Diectories/Conditionals.
I don't believe the compiler will ever eliminate apparently dead code like this. I have never had trouble setting breakpoints on code that could have been eliminated as redundant.
For some scenarios, the compiler can detect if the code is unreachable and eliminate the code.
For instance, the compiler correctly eliminates the "unreachable" portion of the code below.
It will not generate code for that line so:
So there are no blue bullets indicating there is code
Breakpoints put on that line will be marked visually as 'not reachable'
Just tested in Delphi XE, but older Delphi versions have similar behaviour.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
procedure Test;
begin
if (True = False) then
Writeln('Unreachable')
else
Writeln('Reachable');
end;
begin
try
Test();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
It takes quite some while to learn when (or when not) the optimizer on code level and liker level kicks in.
For instance: When you have optimizations turned on, the compiler will also eliminate variables as soon as they are not used.
Sometimes, it even eliminates global symbols.
Danny Thorpe (former Delphi Compiler engineer and Chief Scientist) once wrote a magic method Touch that prevents this.
Just call this Touch method at the end of your method to fool the optimizer during debugging:
procedure Touch(var arg);
begin
end;
--jeroen