Tested with Delphi XE7 Update 1 and Delphi XE8
Create order on Windows OS (7 SP1 x64), MACOSX (10.10.3) and Android (5.0.2):
"class constructor TGlobalClass.Create;" -> "constructor TfmMain.Create;" -> "procedure TfmMain.FormCreate(Sender: TObject);"
Release order on Windows OS and MACOSX:
"TfmMain.FormDestroy" -> "destructor TfmMain.Destroy" -> "class destructor TGlobalClass.Destroy;"
Release order on Android:
"class destructor TGlobalClass.Destroy;" -> "TfmMain.FormDestroy" -> "destructor TfmMain.Destroy"
Question is: why on Android platform CLASS VAR releasing before main form?
Sample of code:
unit uClassVar;
interface
type
TGlobalClass = class
class var F1: Integer;
class constructor Create;
class destructor Destroy;
end;
implementation
{ TX }
class constructor TGlobalClass.Create;
begin
{ Breakpoint there }
F1 := 100;
end;
class destructor TGlobalClass.Destroy;
begin
{ Breakpoint there }
F1 := 200;
end;
end.
Main unit:
unit ufmMain;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics;
type
TfmMain = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
var
fmMain: TfmMain;
z: Integer;
implementation
uses
uClassVar;
{$R *.fmx}
constructor TfmMain.Create;
begin
{ Breakpoint there }
inherited;
end;
destructor TfmMain.Destroy;
begin
{ Breakpoint there }
inherited;
end;
procedure TfmMain.FormCreate(Sender: TObject);
begin
{ Breakpoint there }
TGlobalClass.F1 := -99999;
end;
procedure TfmMain.FormDestroy(Sender: TObject);
begin
{ Breakpoint there }
z := 200;
end;
end.
Project file:
program ClassVar;
uses
System.StartUpCopy,
FMX.Forms,
ufmMain in 'ufmMain.pas' {fmMain},
uClassVar in 'uClassVar.pas';
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TfmMain, fmMain);
Application.Run;
end.
Desktop compilers
Your main form is destroyed when the application object destroys its components. That happens in
FMX.Forms
in theDoneApplication
procedure.And
DoneApplication
is called during shutdown as an exit proc. That exit proc is registered fromTApplication.Run
like this:Class constructors are called from the initialization section of the unit which defines them. So,
TGlobalClass.Create
is called from the initialization ofuClassVar
. Class destructors are called from the finalization section of that same unit.The system shutdown is performed by the
System
unit in_Halt0
. It executes all the exit procs before performing unit finalization. Hence your form is destroyed before the class destructors are called.Mobile compilers
Note that
DoneApplication
is simply not called on Android.This means is that the main form's destruction is being invoked from unit finalization. As each unit is finalized, its finalization sections are executed which result in any global variables leaving scope. Eventually, there are no more references to your main form and so its destructor is executed.
As discussed above, the class destructors are also called from unit finalization. Since on Android, your class destructor executes before the main form is destroyed, it is clear to see that
uClassVar
is finalized before the main form's final reference is released.Now, that makes perfect sense because
uClassVar
is the final unit in the initialization order, and hence the very first unit in the finalization order. If you wanted to ensure thatuClassVar
is finalized later, you need to arrange for it to be initialized sooner. For instance, by changing the uses clause of your .dpr file like so:Now
uClassVar
is the first unit initialized, and hence the last unit finalized.