Delphi and finalization in a unit - delphi

I have two units unitA and unitB.
Class TFoo is declared in unitB.
Is it allways safe to call B.Free in finalization of unitA?
How does it depend on in which order unitA and unitB are in dpr?
Can I be sure that unitB exists when unitA finalization is executed?
unit unitB;
interface
type
TFoo = class
// code...
end;
// code....
end;
unit unitA;
// code..
implementation
uses
unitB;
var
A: TStringList;
B: UnitB.TFoo;
initialization
A:= TStringList.Create;
B:= UnitB.TFoo.Create;
finalization
A.Free;
B.Free; // Is it safe to call?
end.

Yes, you should be fine since B is created in Unit A. The rule is that the Initialization sections are called based on the order they are in the DPR, unless one of the units references another unit. In that case, the referenced unit is initialized first. Finalization is in the reverse order.
In your case Unit B does not have an initialization section, so it is a moot point. It will however use the TFoo definition in Unit B when the Unit A initialization section is executed.
Another word of warning about Initialization and Finalization sections - they happen outside of the global exception handler. Any exception that occurs there just terminates the application. So tracking down and debugging those exceptions can be a pain in large programs. You might consider using your own exception logging in there, just to be sure.

NO. You can try, you can hope but there is no guarantee in order of calling initialization and finalization. See qc72245, qc56034 and many more.
UPDATE:
finalization section is executed in reverse order than initialization. Your example is safe, you don't have dependency on calling initialization sections between units
Delphi can mix calling units (point 1 is still valid, both initialization and finalization sections are swapped)
Example:
unitA // no dependency on unitB
var SomeController;
initialization
SomeController := TSomeController.Create;
finalization
SomeController.Free;
unitB
uses
unitA;
initialization
SomeController.AddComponent(UnitBClass);
finalization
SomeController.RemoveComponent(UnitBClass);
Common (correct) order (99.99%) of calling:
unitA.initialization
unitB.initialization
run...
unitB.finalization
unitA.finalization
But sometimes can Delphi compile file wrong:
unitB.initialization - AV here
unitA.initialization
run...
unitA.finalization
unitB.finalization - and here too
Little offtopic story:
We have quite big project, with Type1 in Unit1, Type2 = class(Type1) in Unit2. Files are ordered in project.dpr and after years and adding Unit200 (no dependency with unit1/2) Delphi starts compiling project with Unit2.Initialization before Unit1.Initialization. Only safe solution is calling your own Init functions from initialization section.

As far as I understand it what you've got should be perfectly valid. A little awkward but valid.
But a better way might be to declare a variable in Unit B and have B initialize/finalize it.
Since initializations happen before any other code is called it will be initialize before it is made available to Unit A as long as it is declared in the uses clause of Unit A.
One other step you might want to consider is taking the unit variable of B one step further and have it as a function call for on demand loading, but that might also be dependant on your usage.
for example
unit unitB;
interface
type
TFoo = class
// code...
end;
// code....
function UnitVarB:TFoo;
implementation
var
gUnitVarB : TFoo;
function UnitVarB:TFoo
begin
if not assigned(gUnitVarB) then
gUnitVarB := TFoo.Create;
result := gUnitVarB;
end;
finalization
if assigned(gUnitVarB) then
gUnitVarB.free; //or FreeAndNil(gUnitVarB);
end;
unit unitA;
// code..
implementation
uses
unitB;
var
A: TStringList;
//code...
...UnitVarB....
//code...
initialization
A:= TStringList.Create;
finalization
A.Free;
end.
I seem to remember somewhere that unit initializations could be expensive in that if a unit that you no longer directly reference is still in your uses clause during a compile, the smart linker will not remove it because of the initialization section. While this may not sound that bad if every unit had an initialization section then most Delphi programs would be MUCH bigger than they already are.
I'm not saying don't use them but my rule of thumb is to use them sparingly.
Your initial code example breaks that rule. I thought I'd mention it.
Ryan

In the specific situation you are showing here, you will be alright. But it wouldn't take that much refactoring before it starts going wrong.
Delphi does a pretty good job making sure units stays in memory as long as they are needed. But it can only do so if it knows a unit is needed.
My classical example on the topic is a unit containing nothing but an objectlist
unit Unit1;
interface
uses
Contnrs;
var
FList : TObjectList;
implementation
initialization
FList := TObjectList.Create(True);
finalization
FList.Free;
end.
Unit1 is only explicitly dependant on Contnrs. Delphi will only ensure the Contnrs unit (and probably also "subdependant" units, though I'm not 100% sure) is still loaded in memory. If a TForm is added in the list, the Forms unit might be already finalized when FList.free is called it will crash when it tries to free the TForm it contains. Delphi has no way to know Unit1 requires the Forms unit. In this specific case, it will depend on the order units are declared in the dpr.

Yes, that is safe. You can simplify the compiler's job by declaring UnitB prior to UnitA in dpr file, but the compiler will resolve the references in any case.

In the spirit of full disclosure, I haven't developed in Delphi since 2005. However, I developed in Delphi exclusively starting with Delphi 1 in 1996, and was certified in Delphi 5 in 2001. That being said, my use of the finalization section was rare. The only time I would use it is if I needed to set up something special in the .dpr. That typically only occurred if I was doing custom component development, AND there were some dependencies that I needed to manage using other custom components I was developing.
For typical application development, I stayed away from the initialization/finalization section and just used design patterns like singletons, facades and factories to manage the creation and management of my classes. The built-in garbage collector was good enough for 98.5% of my projects.
To answer your question, you need to set up a dependency on TFoo in your UnitA code, and, as Ryan suggested, make sure it's assigned prior to destruction. That being said, I encourage you to make sure that the use of the initialization/finalization section is necessary before you invest too much time with it.

Related

changing the initialization order of the unit in Delphi

I'm using Delphi XE7 for developing windows 32 bit application.
My application contains many units, which has an initialization section. I need to initialize one particular initialization section at first.
Is it possible to set the priority?
I have tried to write the initialization section in dpr file, but the compiler has rejected this.
Please help me to execute the particular initialization section at first. Thanks in advance.
In simple terms, initialization sections are executed in the order in which the units are introduced in any uses clauses. But it is a little more complicated than that due to the fact that initialization of a unit is performed only after the initialization of any units that that unit itself references (where they have not already been initialized).
i.e. Given:
program Foo;
uses
Unit1,
Unit2,
Unit3;
unit Unit1;
interface
uses
Unit3;
Then the unit initialization order will be:
Unit3
Unit1
Unit2
This is because Unit1 introduces Unit3, so even though Unit1 is listed first in the dpr uses, Unit3 is in fact initialized first, followed by the initialization of Unit1.
If you remember that the initialization section occurs after any uses clauses in a unit, it does make sense.
Therefore the only way to be absolutely sure of any one unit being initialized before any other is to list it first in the DPR uses clause and for that unit to take no dependencies on any other units (except where those units are not dependent on, or otherwise interfere with, the initialization being performed) .
It need not necessarily be strictly first of course. e.g. if you are using a replacement memory manager (such as FastMM) then this will absolutely need to be the very first unit listed in your dpr uses clause. You simply need to make sure that the unit you need to be initialised before any other (of your units) is then listed before any other unit which might bring your other units in:
program Foo;
uses
FastMM, // MUST be first but won't bring any of 'my' units in, so this is OK
SysUtils, // These too are fine coming next because again they don't
Forms, // reference 'my' units
MyInitUnit, // <- This is where it is important to list 'my' guaranteed first/earliest
// initialisated unit of all 'my' units
MyFirstAppUnit, // And now the rest ...
etc;
Of course, if the unit that you wish to initialise first does need to be initialised before any other, including RTL units (in the same way that FastMM etc need to be) then you would need to reflect that in the dpr uses list by declaring your unit earlier still.
The initialization sections are executed in the order that the units appear in the uses clause.
So, you may force your unit to initialize first by moving it up in the uses list.

Is it possible to use a library just for design time in delphi?

I am trying to write a component which is loading 3D objects from obj files.
I am using ToolsAPI library for GetActiveProject.FileName. I added designide.dcp to Requiers part in the bpl. I registered my object and in design when I put an instance of this object on a TViewPort3D which I put before everything is OK and I can see the object from the obj file is loaded in the scene, but when I try to compile the project I get an error that says ToolsAPI.dcu not found.
The procedure that I use for loading the obj file is (Type of Model variable is TModel3D) :
procedure TMyObject.LoadModel(fileName: string);
begin
if(csDesigning in ComponentState)then
Model.LoadFromFile(IncludeTrailingPathDelimiter(ExtractFilePath(GetActiveProject.FileName))+'Obj\'+filename)
else
Model.LoadFromFile(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'Obj\'+filename);
end;
This procedure is used in constructor as follow (TMyObject inherited from TDummy):
constructor TMyObject.Create(AOwner:TComponent)
begin
inherited;
Model:=TModel3D.Create(Self);
Model.Parent:=Self;
LoadModel('Object1.obj');
end;
Is there anyway to prevent using the ToolsAPI library when the host project for the component is about to compile?
I just thinking about something like directives as follow.
{$IFDEF DESIGNTIME}
uses ToolsAPI;
{$ENDIF}
But is it possible to do such a thing?
It sounds as though you are trying to compile the design time code into a run time project. Either a run time package, or an executable. That's not allowed. You simply cannot compile any of the ToolsAPI units into a project that is not a design time package.
You can certainly use conditional compilation to exclude the ToolsAPI units, but you will have to define your own conditional define. There is no built-in conditional that will serve your needs.
But using conditional compilation is probably not the best solution. Typically you would separate the code that used Tools API into distinct units, and only include those units in the design time projects.
So the code for your component would be split into, say, two units. The first unit, uMyComp.pas, say, contains the bulk of the code. This unit declares the component and provides its implementation. Nothing in uMyComp.pas makes any reference to ToolsAPI. The second unit, uMyCompReg.pas say, performs the component registration and any other tasks that require the ToolsAPI. There is a dependency between these units in that uMyCompReg.pas uses uMyComp.pas. Then your design time package will include both units, and any other projects that are not design time will include only uMyComp.pas.
You could achieve the same effect using conditionals. The design time project would define a conditional to indicate that this was design time. So the project settings might include a definition of a conditional named DESIGNTIME. Then all the code for your component would reside in a unit named uMyComp.pas, say. Any code related to design time would be conditional on DESIGNTIME. And any other projects that included uMyComp.pas would not have DESIGNTIME defined and so would omit the design time only code.
Whilst this is possible it is not, in my view, the best way to solve the problem. Indeed if you look around the wealth of open source examples of component development I'd be surprised if you found any that handled the separation of design time code from run time code using conditionals.
How would you separate the ToolsAPI code into a design time unit? Here's the problem method:
procedure TMyObject.LoadModel(fileName: string);
begin
if csDesigning in ComponentState then
Model.LoadFromFile(IncludeTrailingPathDelimiter(
ExtractFilePath(GetActiveProject.FileName))+'Obj\'+filename)
else
Model.LoadFromFile(IncludeTrailingPathDelimiter(
ExtractFilePath(ParamStr(0)))+'Obj\'+filename);
end;
First of all, let's look at the commonality of this code. The first think to observe is that the outsides of the call to LoadFromFile are the same. Only in the middle, the choice of directory, is there variation. So let's write it like this:
procedure TMyObject.LoadModel(fileName: string);
var
ModelDir: string;
begin
if csDesigning in ComponentState then
ModelDir := ExtractFilePath(GetActiveProject.FileName)
else
ModelDir := ExtractFilePath(ParamStr(0));
Model.LoadFromFile(IncludeTrailingPathDelimiter(ModelDir)+'Obj\'+filename);
end;
The problem for you is how to move GetActiveProject.FileName into the design time code. You need to use dependency injection (DI) to do this. Allow some other party to supply the logic. You need to make TMyObject ignorant of this particular detail. You could use a DI framework for this, but that's perhaps a little heavyweight just for this one task. So instead let's declare a class variable that holds a function pointer:
type
TMyObject = class(...)
...
public
class var GetModelDir: TFunc<string>;
end;
This function point allows other parties, external to the class, to specify how the model directory is located. Now LoadModel becomes:
procedure TMyObject.LoadModel(fileName: string);
var
ModelDir: string;
begin
if Assigned(GetModelDir) then
ModelDir := GetModelDir()
else
ModelDir := ExtractFilePath(ParamStr(0));
Model.LoadFromFile(IncludeTrailingPathDelimiter(ModelDir)+'Obj\'+filename);
end;
At this point, your code can now be used outside of a design time package. The next step is to add code to specify GetModelDir at design time. This code goes in the design time only unit that also registers the component. The obvious place for the code is in the initialization section of that unit. It looks like this:
initialization
TMyObject.GetModelDir :=
function: string
begin
Result := GetActiveProject.FileName;
end;
I've used anonymous methods here, but you could equally use method of object, or plain old functional types, depending on your Delphi version.
Yes, but preferably not with conditional defines as this would create far more complications and restrictions than it's worth.
You need to separate your code into different units according to whether it's design-time code or run-time code.
E.g. For a single component, the bulk of the (with no ToolsAPI dependency) goes into one unit.
A second unit performs component registration and perhaps provides custom design-time editors for the component.
The second unit uses the first and you have a clean separation without conditional defines.
You then create 2 separate packages: design-time and run-time.
The design time package will have a dependency on the ToolsAPI.
Make sure that none of the run-time units use any of the design-time units.
If any design-time units use run-time units (very likely) then the design-time package will require the run-time package.
With the above package structure, your application that uses your new components should only have dependencies on the run-time units.

getting around circular references in Delphi [duplicate]

This question already has answers here:
Delphi Enterprise: how can I apply the Visitor Pattern without circular references?
(4 answers)
Closed 8 years ago.
Is there a way of getting around circular unit references in Delphi?
Maybe a newer version of delphi or some magic hack or something?
My delphi project has 100 000+ lines of code mostly based on singleton classes. I need to refactor this, but that would mean several months of "circular reference" hell :)
I've been maintaining close to a million lines of legacy code for the past 10 years so I understand your pain!
In the code that I maintain, when I've encountered circular uses, I frequently have found that they are caused by constants or type definitions in unit A that are needed by unit B. (Sometimes it's also a small bit of code (or even, global variables) in Unit A that is also needed by unit B.
In this situation (when I'm lucky!) I can carefully extract those parts of the code into a new unit C that contains the constants, type definitions, and shared code. Then units A and B use unit C.
I post the above with some hesitance because I'm not an expert on software design and realize there are many others here who are far more knowledgeable than I am. Hopefully, though, my experience will be of some use to you.
It seems you have quite serious code design issues. Besides many signs of such issues, one is the circular unit reference. But as you said: you cannot refactor all the code.
Move all what is possible to the implementation section. They are allowed to have circular references.
To simplify this task you can use 3rd party tools. I would recommend
Peganza Pascal Analyzer - it will suggest what you can move to the implementation section. And will give you many more hints to improve your code quality.
Use the implementation section uses whenever possible, and limit what's in the interface uses clause to what has to be visible in the interface declarations.
There is no "magic hack". Circular references would cause an endless loop for the compiler (unit A requires compiling unit B which requires compiling unit A which requires compiling unit B, etc.).
If you have a specific instance where you think you cannot avoid circular references, edit your post and provide the code; I'm sure someone here can help you figure out how to get it fixed.
There is many ways to avoid circular references.
Delegates.
Way too often, an object will execute some code that should be done in an event instead than being done by the object itself. Whether it is because the programmer working on the project was too short on time(aren't we always?), didn't have enough experience/knowledge or was just lazy, some code like this eventually end up in applications. Real world exemple : TCPSocket component that directly update some visual component on the application's MainForm instead of having the main form register a "OnTCPActivity" procedure on the component.
Abstract Classes/Interfaces. Using either of them allow to remove a direct dependance between many units. An abstract class or an interface can be declared alone in its own unit, limiting dependancies to a maximum. Exemple: Our application has a debug form. It has uses on pretty much the whole application as it displays information from various area of the application. Even worse, every form that allows to show the debug form will also also end up requiring all the units from the debug form. A better approach would be to have a debug form which is essentially empty, but that has the capacity to register "DebugFrames".
TDebugFrm.RegisterDebugFrame(Frame : TDebugFrame);
That way, the TDebugFrm has no dependancies of its own (Except than on the TDebugFrame class). Any and all unit that requires to show the debug form can do so without risking to add too many dependancies either.
There are many other exemple... I bet it could fill a book of its own. Designing a clean class hierarchy in a time efficient fashion is pretty hard to do and it comes with experience. Knowing the tools available to achieve it and how to use them is the 1st step to achieve it. But to answer your question... There is no 1-size-fit-all answer to your question, it's always to be taken on a case by case basis.
Similar Question: Delphi Enterprise: how can I apply the Visitor Pattern without circular references?
The solution presented by Uwe Raabe uses interfaces to resolve the circular dependency.
Modelmaker Code Explorer has a really nice wizard for listing all the uses, including cycles.
It requires that your project compiles.
I agree with the other posters that it is a design issue.
You should carefully look at your design, and remove unused units.
At DelphiLive'09, I did a session titled Smarter code with Databases and data aware controls which contains quite few tips on good design (not limited to DB apps).
--jeroen
I found a solution that doesn't need the use of Interfaces but may not resolve every issues of the circular reference.
I have two classes in two units: TMap and TTile.
TMap contains a map and display it using isometric tiles (TTile).
I wanted to have a pointer in TTile to point back on the map. Map is a class property of TTile.
Class Var FoMap: TObject;
Normaly, you will need to declare each corresponding unit in the other unit... and get the circular reference.
Here, how I get around it.
In TTile, I declare map to be a TObject and move Map unit in the Uses clause of the Implementation section.
That way I can use map but need to cast it each time to TMap to access its properties.
Can I do better? If I could use a getter function to type cast it. But I will need to move Uses Map in the Interface section.... So, back to square one.
In the Implementation section, I did declare a getter function that is not part of my class. A Simple function.
Implementation
Uses Map;
Function Map: TMap;
Begin
Result := TMap(TTile.Map);
End;
Cool, I thought. Now, every time I need to call a property of my Map, I just use Map.MyProperty.
Ouch! Did compile! :) Did not work the expected way. The compiler use the Map property of TTile and not my function.
So, I rename my function to aMap. But my Muse spoke to me. NOOOOO! Rename the Class Property to aMap... Now I can use Map the way I intented it.
Map.Size; This call my little function, who typecast aMap as TMap;
Patrick Forest
I gave a previous answer but after some thinking and scratching I found a better way to solve the circular reference problem. Here my first unit who need a pointer on an object TB define in unit B.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, b, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FoB: TB;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
FoB := TB.Create(Self);
showmessage(FoB.owner.name);
end;
end.
Here the code of the Unit B where TB has a pointer on TForm1.
unit B;
interface
Uses
dialogs, Forms;
type
TForm1 = class(TForm);
TB = class
private
FaOwner: TForm1;
public
constructor Create(aOwner: TForm);
property owner: TForm1 read FaOwner;
end;
implementation
uses unit1;
Constructor TB.create(aOwner: TForm);
Begin
FaOwner := TForm1(aOwner);
FaOwner.Left := 500;
End;//Constructor
end.
And here why it compiles. First Unit B declare the use of Unit1 in the implementation section. Resolving immediately the circular reference unit between Unit1 et Unit B.
But to allow Delphi to compile, I need to give him something to chew on the declaration of FaOwner: TForm1. So, I add stub class name TForm1 who match the declaration of TForm1 in Unit1.
Next, when come the time to call the constructor, TForm1 is able to pass itself has the parameter. In the constructor code, I need to typecast the aOwner parameter to Unit1.TForm1. And voilĂ , FaOwner his set to point on my form.
Now, if the class TB need to use FaOwner internally, I don't need to typecast it every time
to Unit1.TForm1 because both declaration are the same. Note that you could set the declaration of to constructor to
Constructor TB.create(aOwner: TForm1);
but when TForm1 will call the constructor and pass itself has a parameter, you will need to typecast it has b.TForm1. Otherwise Delphi will throw an error telling that both TForm1 are not compatible. So each time you call the TB.constructor you will need to typecast to the appropriate TForm1. The first solution, using a common ancestor, his better. Write the typecast once and forget it.
After I posted it, I realized that I made a mistake telling that both TForm1 were identical. They are not Unit1.TForm1 has components and methods that are unknown to B.TForm1. Has long TB doesn't need to use them or just need to use the commonality given by TForm you're okay. If you need to call something particular to UNit1.TForm1 from TB, you will need to typecast it to Unit1.TForm1.
I try it and test it with Delphi 2010 and it compiled and worked.
Hope it will help and spare you some headache.

How to access delphi function at DPR scope

I have a problem with maintenance on an old Delphi program (D7). A lot of the program logic is in the DPR file (this is not a windowed program), with some units providing things like access to the database. We need to get some debug out of the DB unit, but the debug functionality is in the DPR. We can't easily strip the debug functionality out, because it uses stuff that's unique to the DPR, like its main pipe. Separating it out would be like trying to tease apart spaghetti and meatball sauce.
So how do we call a function that's declared at the DPR scope from a subordinate used unit? What's the equivalent of the :: operator in C++ ?
Please don't tell me to redesign the app. I'd love to, but we won't be given the necessary time. Plus if we redesigned this puppy, it wouldn't be in Delphi.
You can declare a method variable in the unit that matches the signature of the function in the DPR. At the very beginning of the program you set the method variable to the function. Inside the unit you call the method variable.
Example:
(DPR)
uses
Unit1;
function DoSomething(Par: Integer): Integer;
begin
...
end;
...
begin
DoSomethingVar := DoSomething;
...
end;
(unit)
unit Unit1;
interface
...
var
DoSomethingVar: function(Par1: Integer): Integer;
...
implementation
...
SomeResult := DoSomethingVar(SomeParameter);
...
You can't. The unit hierarchy is rigid.
There are two possible options:
pull out the relevant parts of the .dpr to a new unit. Keep in mind that moving uses to the implementation can break import cycles. The createform* stuff probably isn't safe to move, that would probably upset the project manager.
or define a few callback functions (function,method types, like functionpointer in C), and move code out of the relevant unit initialization to a procedure that you call from the .dpr if necessary.
I don't know how to use functions from .dpr in other units, but if you have to change code simply change .dpr to normal unit and then use it's functions/routines in new .dpr and in others units.
.dpr is the most fundmental pascal project file.
We can use any unit files in the project, and so, you can use
the functions/procedures in the units.
If necessary, you can prefix the unit name for accessing the
function/procedure.
If the function/procedure belongs to specific class, you need
to create an instance to access the function/procedure because
it's a method.
Anyway, Delphi uses object pascal as its core, you can access
any necessary method/procedure/function/properties with legal
pascal concepts and object pascal concepts.
No matter which file you need to call it, and the only one except
is the decalaration file for some external library.

Global variables in Delphi

I have a console application written in Delphi.
I saw that I can have global variables by assigning them to unit scopes, but in a console application I don't use units (from what I've understood it's forms-only).
Nope, a unit is not equivalent to a form.
A unit is a module which contains part of your program. Each form is a separate unit but a unit does not have to contain a form.
Each unit has an interface section and a implementation section. The declarations in the interface section are visible to all units that use the unit:
unit A;
interface
type
TMyClass = class
end;
implementation
end.
unit B;
interface
uses
A; // I can now see and use TMyClass.
You can declare global variables by declaring them in a unit:
unit A;
interface
var
GVar1 : Integer;
implementation
var
GVar2 : Integer;
end.
GVar1 is visible and can be modified by all units using unit A. GVar2 is only visisble by the code of unit A because it is defined in the implementation section.
I strongly advice against using globals in the interface section because you have no control over them (because anybody can change them). If you really need a global, you better define it in the implementations section and provide access functions.
By the way, you can see a unit as a kind of a class (with a single instance). It even has a way to construct and destruct:
unit A;
interface
type
TMyClass = class
end;
implementation
initialization
// Initialize the unit
finalization
// Free resources etc. You can olny have a finalization if you have an initialization.
end.
If you want global variable declare it in interface section of your unit.
PS Console aplication can use units.
PPS Take some time and read Delphi documentation, it explains Delphi language pretty well.

Resources