Skip to content

Global managed record variable isn’t initialized if not referenced in the same unit.

...And, conversely, always initialized even if its referencers aren’t called by anyone (though the latter might be by design, as it is at least always and consistently finalized, even with empty main :D).

Example:

main_program.pas

{$mode objfpc} {$longstrings on}
uses
	UnitA;

begin
	Con.Dump('Main');
end.

UnitA.pas

{$mode objfpc} {$longstrings on} {$modeswitch advancedrecords}
{$define enable_UseFromA}
unit UnitA;

interface

type
	Console = record
		Initialized: boolean;
		procedure Dump(const where: string);
		class operator Initialize(var self: Console);
		class operator Finalize(var self: Console);
	end;

{$ifdef enable_UseFromA}
	procedure UseFromA;
{$endif}

var
	Con: Console;

implementation

	procedure Console.Dump(const where: string);
	begin
		if not Initialized then write('/UNINITIALIZED/ ');
		writeln(where);
	end;

	class operator Console.Initialize(var self: Console);
	begin
		writeln('Console.Initialize');
		self.Initialized := true;
	end;

	class operator Console.Finalize(var self: Console);
	begin
		self.Initialized := false;
		writeln('Console.Finalize');
	end;

{$ifdef enable_UseFromA}
	procedure UseFromA;
	begin
		Con.Dump('UseFromA');
	end;
{$endif}

end.

Output without enable_UseFromA:

/UNINITIALIZED/ Main
Console.Finalize

Output with enable_UseFromA:

Console.Initialize
Main
Console.Finalize

Note that in the second case, UseFromA is not called by anyone and even (or should I say “of course”) absent from the binary.

Edited by Rika
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information