Recent

Author Topic: Questions about initialization  (Read 3434 times)

Okoba

  • Hero Member
  • *****
  • Posts: 533
Questions about initialization
« on: January 07, 2023, 08:13:04 am »
I have a couple of questions and confusions around initialization and I appreciate any help for clarifying them.

Question1:
I always faced this one, but never find out why.
Considering these two Tests:

Test1:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. var
  4.   A: array[0..10] of integer;
  5.   I: integer;
  6. begin
  7.   for I := 0 to High(A) do
  8.     WriteLn(A[I]);
  9.   ReadLn;
  10. end.

Test2:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3.   procedure Test;
  4.   var
  5.     A: array[0..10] of integer;
  6.     I: integer;
  7.   begin
  8.     for I := 0 to High(A) do
  9.       WriteLn(A[I]);
  10.   end;
  11.  
  12. begin
  13.   Test;
  14.   ReadLn;

Why in Test1, (as far as I know), A is zeroed, but not in Test2?
In both cases FPC warns about not initialized value.

Question2:
Why Initialize(A); does not zero the array?
Code: Pascal  [Select][+][-]
  1.   procedure Test;
  2.   var
  3.     A: array[0..10] of integer;
  4.     I: integer;
  5.   begin
  6.     Initialize(A);
  7.     for I := 0 to High(A) do
  8.       WriteLn(A[I]);
  9.   end;      
For example if I use Initialize on a record, it will zero any value in it, but not for arrays. And it is documented as "Initializing means zeroing out the memory area".
What is the logic behind this?
I guess, one can say, it does Initialize the memory of array, but not the induvial items, but the array in it self is a type, so why not Initializing (zeroing out) it too?

Question3:
And to add to confusion of myself, Initialize is documented as "In this sense it is close in functionality to Default, but Default requires an already initialized variable."
But if I try to do this, I will get a zeroed array, so they are not the same.

Code: Pascal  [Select][+][-]
  1.   procedure Test;
  2.   type
  3.     TA = array[0..10] of integer;
  4.   var
  5.     A: TA;
  6.     I: integer;
  7.   begin
  8.     A := Default(TA);
  9.     for I := 0 to High(A) do
  10.       WriteLn(A[I]);
  11.   end;  

Question4:
As said in documentation, "Default requires an already initialized variable." What does it mean? Is it best practice to call Initialize first and then Default?

Considering this sample:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3.   {$mode delphi}
  4. type
  5.  
  6.   { TTest }
  7.  
  8.   TTest = record
  9.     I: integer;
  10.     class operator Initialize(var AValue: TTest);
  11.     class operator Finalize(var AValue: TTest);
  12.     class operator AddRef(var AValue: TTest);
  13.     class operator Copy(constref A: TTest; var B: TTest);
  14.   end;
  15.  
  16.   class operator TTest.Initialize(var AValue: TTest);
  17.   begin
  18.     WriteLn('Initialize: ', QWord(@AValue));
  19.   end;
  20.  
  21.   class operator TTest.Finalize(var AValue: TTest);
  22.   begin
  23.     WriteLn('Finalize: ', QWord(@AValue));
  24.   end;
  25.  
  26.   class operator TTest.AddRef(var AValue: TTest);
  27.   begin
  28.     WriteLn('AddRef: ', QWord(@AValue));
  29.   end;
  30.  
  31.   class operator TTest.Copy(constref A: TTest; var B: TTest);
  32.   begin
  33.     WriteLn('Copy: ', QWord(@A), ' : ', QWord(@B));
  34.   end;
  35.  
  36.   procedure Test1;
  37.   var
  38.     V: TTest;
  39.   begin
  40.   end;
  41.  
  42.   procedure Test2;
  43.   var
  44.     V: TTest;
  45.   begin
  46.     Initialize(V);
  47.   end;
  48.  
  49.   procedure Test3;
  50.   var
  51.     V: TTest;
  52.   begin
  53.     V := Default(TTest);
  54.   end;
  55.  
  56. begin
  57.   WriteLn('Test1');
  58.   Test1; //No Initialize
  59.   WriteLn('Test2');
  60.   Test2; //Two Initialize on same pointer!
  61.   WriteLn('Test3');
  62.   Test3; //One Initialize
  63.   ReadLn;
  64.  
  65.   //Log:
  66.   //Test1
  67.   //Test2
  68.   //Initialize: 20971068
  69.   //Initialize: 20971068
  70.   //Finalize: 20971068
  71.   //Test3
  72.   //Initialize: 20971068
  73.   //Copy: 20971064 : 20971068
  74.   //Finalize: 20971068
  75. end.


Question5:
Why Test2 is initialize V two times for the same pointer?

Question6:
At Test3, Pointer 20971068 is initialized, but not 20971064. But FPC copies 20971064 to 20971068. Why? and how should I manage it to not duplicated a cost of copy? I thought Default, makes the value default, but it seem it makes a initialized(!) value and copy it to the variant.

Documentation of initialize: https://www.freepascal.org/docs-html/rtl/system/initialize.html


For future readers:
https://forum.lazarus.freepascal.org/index.php/topic,62706.msg474502.html#msg474502
« Last Edit: March 17, 2023, 10:30:25 pm by Okoba »

speter

  • Sr. Member
  • ****
  • Posts: 349
Re: Questions about initialization
« Reply #1 on: January 07, 2023, 08:30:38 am »
Q1: I believe local variables are not initialised.
see https://www.freepascal.org/docs-html/ref/refse24.html

Q2: initialize() works on managed types, which I believe your array is not.
https://www.freepascal.org/docs-html/rtl/system/initialize.html

Q3: default() is the way to go :)

Q4: default's documentation (link below); does not say that default "requires an already initialized variable". I don't know why initialize's docs say that, it doesn't make any sense to me.
https://www.freepascal.org/docs-html/rtl/system/default.html


cheers
S.





I climbed mighty mountains, and saw that they were actually tiny foothills. :)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Questions about initialization
« Reply #2 on: January 07, 2023, 09:02:15 am »
The docs could have been more specific about Initialize and Finalize applying to managed variable types only.
For instance the pseudo signature could have been given as:
procedure Initialize(
  var T: TAnyManagedType;
  ACount: SizeInt = 1
);

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Questions about initialization
« Reply #3 on: January 07, 2023, 09:14:06 am »
@4: fixed length arrays are an exception: you can call default() on it.
There is one caveat: you need to provide a type for the fixed length array.
E.g:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}{$ifdef mswindows}{$apptype console}{$endif}
  2. procedure test;
  3. type
  4.   TMyArray= array[0..9] of integer; // default() needs a type
  5. var
  6.   a:TMyArray;
  7.   i:integer;
  8. begin
  9.   for i in a do write(i,' ');writeln;// stack is dirty, array may contain random values
  10.   a:=Default(TMyArray); // clean the static array
  11.   writeln('===========================================');
  12.   for i in a do write(i,' ');writeln; //array contains only zero's
  13. end;
  14.  
  15. begin
  16.   test;
  17.   readln;
  18. end.

Example output (different for every run):
Code: [Select]
4194304 0 0 0 1 0 503 0 41120 1
===========================================
0 0 0 0 0 0 0 0 0 0

So the documentation for Initialize() is wrong.It should read: "an initialized variable or a type.".
As long there is a type, default will work happily.
« Last Edit: January 07, 2023, 09:58:34 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6686
Re: Questions about initialization
« Reply #4 on: January 07, 2023, 09:56:53 am »
Q1: I believe local variables are not initialised.
see https://www.freepascal.org/docs-html/ref/refse24.html

i.e. Local variables are on the stack, which is reused repeatedly hence might contain stale data.

Global variables might (depending on implementation details) be in a separate global space or might get the first bit of stack.

In the general case, it might be best not to assume that this is initialised: a great deal depends on the language implementation, the linker, and the behaviour of the OS when it allocates and loads initial memory.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Questions about initialization
« Reply #5 on: January 07, 2023, 10:42:37 am »
i.e. Local variables are on the stack, which is reused repeatedly hence might contain stale data.

Global variables might (depending on implementation details) be in a separate global space or might get the first bit of stack.

In the general case, it might be best not to assume that this is initialised: a great deal depends on the language implementation, the linker, and the behaviour of the OS when it allocates and loads initial memory.

MarkMLl
Well,
1. stack allocations are almost always dirty, but there are exceptions, e.g. advanced records with an initialize operator.
2. with the default memory manager heap memory, globals are always initialized
3. when you use a different memory manager that may not be the case.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Okoba

  • Hero Member
  • *****
  • Posts: 533
Re: Questions about initialization
« Reply #6 on: January 07, 2023, 10:45:43 am »
Thank you all for the help.
For now I consider Q1 as answered, thanks @MarkMLl. Maybe a hint in documentation helps future people, although FPC warning of not initialized value should be enough, but there will curious people like me for sure.

I still like to find better understating of Q2, Q3 and Q4, and based on the discussion I added Q5 and Q6 too.

I consider myself a newbie, but initialization seems more complicated than it should. I like to prevent calling Fill or FillZero on managed types as simply it is not "clean".
Pascal has strong typing system, calling memory functions on types seems, ugly and dangerous.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Questions about initialization
« Reply #7 on: January 07, 2023, 11:01:10 am »
Here's an example for advanced records even if allocated on the stack:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}{$ifdef mswindows}{$apptype console}{$endif}{$modeswitch advancedrecords}
  2. type
  3.   TMyRecord = record
  4.    a:array[0..9] of integer;
  5.    class operator initialize(var R:TMyRecord);
  6.   end;
  7.    
  8.    class operator TMyRecord.initialize(var R:TMyRecord);
  9.    var i:integer;
  10.    begin
  11.      R :=Default(TMyRecord);
  12.    end;
  13.    
  14. procedure test;  
  15. var
  16.   a:TMyRecord;  //implicit initialization even if on the stack.
  17.   i:integer;
  18. begin
  19.   for i in a.a do write(i,' ');writeln;// stack is dirty, but the record is initialized on declaration.
  20. end;
  21.  
  22. begin
  23.   test;
  24.   readln;
  25. end.
« Last Edit: January 07, 2023, 11:10:10 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Okoba

  • Hero Member
  • *****
  • Posts: 533
Re: Questions about initialization
« Reply #8 on: January 07, 2023, 11:05:06 am »
@Thaddy thanks for the sample.
So if I access the Record, it will be implicitly initialized. But compiler still warns me that it is not initialized, and if I try to add "Initialize(A);" it will initialize the record, two times, and it is not okay.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Questions about initialization
« Reply #9 on: January 07, 2023, 11:17:37 am »
My example should work out of the box without any warnings or errors.
You must have made a mistake, maybe a type somewhere? Maybe forgot the modeswitch? or maybe you compiled with -Sew? The latter is the only reason I can find that gives a compile time error, which is actually a compiler bug, but one that is not easy to fix....
You can fix my code like this to prevent this happening:
Code: Pascal  [Select][+][-]
  1. {$push}{$warn 5089 off}  
  2. procedure test;
  3. var
  4.   a:TMyRecord;  //implicit initialization even if on the stack.
  5.   i:integer;
  6.  begin
  7.   for i in a.a do write(i,' ');writeln;// stack is dirty, array may contain random values
  8. end;
  9. {$pop}
« Last Edit: January 07, 2023, 11:29:10 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Okoba

  • Hero Member
  • *****
  • Posts: 533
Re: Questions about initialization
« Reply #10 on: January 07, 2023, 11:22:11 am »
I attached an screenshot of your code, on today trunk version of Lazarus and FPC, that warns me about not initialized a.

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Questions about initialization
« Reply #11 on: January 07, 2023, 11:29:52 am »
Look at my last reply, posts crossed. It is an overzealous compiler warning shown as error because you specified that. That is a bug, but not yours. By elimination the warning/error 5089 locally, the compiler won't give an error, nor a warning. In an ideal world this should be fixed, but there are bug reports for that issue and related (variables for which setlength() can be called) marked as won't fix.
« Last Edit: January 07, 2023, 11:45:50 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Okoba

  • Hero Member
  • *****
  • Posts: 533
Re: Questions about initialization
« Reply #12 on: January 07, 2023, 12:14:12 pm »
Do you have a link to such issue? Or know the reason of wont fix?

Thaddy

  • Hero Member
  • *****
  • Posts: 14373
  • Sensorship about opinions does not belong here.
Re: Questions about initialization
« Reply #13 on: January 07, 2023, 12:52:29 pm »
Do you have a link to such issue? Or know the reason of wont fix?
As far as I know, mostly from FPK, Jonas and PascalDragon, the reason is that it is simply too complex to fix and work-arounds exist.
You can search the bug tracker for "variable not initialized"
Too many entries to link to...
[EDIT]
Well, specify -OoDFA and the warning disappears....here... But only without -Sew.
« Last Edit: January 07, 2023, 01:10:31 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5481
  • Compiler Developer
Re: Questions about initialization
« Reply #14 on: January 08, 2023, 04:23:44 pm »
2. with the default memory manager heap memory, globals are always initialized
3. when you use a different memory manager that may not be the case.

Global variables are not initialized by the memory manager. They are initialized either by the OS as part of loading the binary or by the startup code in the executable. The memory manager has absolutely no knowledge about global variables.

 

TinyPortal © 2005-2018