I'll look into a proper bug report today. Thanks for confirming the bug
Regarding the "strange creation":
I try to avoid global vars and keep singleton vars strictly within the class if necessary. That is why I use class constructor and class destructor instead of initialization and finalization of the unit (also makes debugging easier).
Performance is also one reason I construct the singleton upon first use instead in initialization. And here, with such a huge framework as the Lazarus IDE is, it also ensures that the object is available when needed. I simply use it to avoid issues when orders of code using my code changes.
Why do you think class constructor and class destructor are not used?
I just wrote a simple test to confirm they're indeed called (not on first and last class use as I was expecting, but before initialization / after finalization), without me having to manually trigger them. Maybe you could elaborate what you meant
class constructor TTestClass.Create;
TestClassConstructorUnit.initialization
TestClassConstructor.begin#1
constructor TTestClass.Create;
procedure TTestClass.Test;
TestClassConstructor.begin#2
TestClassConstructorUnit.finalization
class destructor TTestClass.Destroy;
destructor TTestClass.Destroy;
From:
program TestClassConstructor;
{$mode objfpc}{$H+}
uses
SysUtils,
Classes,
TestClassConstructorUnit;
begin
WriteLn('TestClassConstructor.begin#1');
TTestClass.Instance.Test;
WriteLn('TestClassConstructor.begin#2');
end.
unit TestClassConstructorUnit;
{$mode objfpc}{$H+}
interface
uses
Classes,
SysUtils;
type
{ TTestClass }
TTestClass = class
private
class var FInstance: TTestClass;
public
class constructor Create;
class destructor Destroy;
class function Instance: TTestClass;
public
constructor Create;
destructor Destroy; override;
procedure Test;
end;
implementation
{ TTestClass }
class constructor TTestClass.Create;
begin
WriteLn('class constructor TTestClass.Create;');
FInstance := nil;
end;
class destructor TTestClass.Destroy;
begin
WriteLn('class destructor TTestClass.Destroy;');
FInstance.Free;
end;
class function TTestClass.Instance: TTestClass;
begin
if not Assigned(FInstance) then begin
FInstance := TTestClass.Create;
end;
Result := FInstance;
end;
constructor TTestClass.Create;
begin
WriteLn('constructor TTestClass.Create;');
end;
destructor TTestClass.Destroy;
begin
WriteLn('destructor TTestClass.Destroy;');
inherited Destroy;
end;
procedure TTestClass.Test;
begin
WriteLn('procedure TTestClass.Test;');
end;
initialization
WriteLn('TestClassConstructorUnit.initialization');
finalization;
WriteLn('TestClassConstructorUnit.finalization');
end.
Thanks for informing me about the RemoveHandler exception on ending Lazarus. On Windows I simply don't see this since I don't start Lazarus from the console. I probably should look for some Lazarus closedown event instead to remove the handlers!