Recent

Author Topic: Initializing a record containing three dynamic arrays  (Read 2504 times)

peardox

  • Jr. Member
  • **
  • Posts: 70
Initializing a record containing three dynamic arrays
« on: September 29, 2020, 11:43:31 am »
I've got some simple records like this...

Code: Pascal  [Select][+][-]
  1. type
  2.   TRecA = record
  3.     f1: String;
  4.     f2: String;
  5.     f3: String;
  6.   end;
  7.   TRecAArray = Array of TRecA;
  8.  
  9.   TRecB = record
  10.     f1: String;
  11.     f2: String;
  12.     f3: String;
  13.   end;
  14.   TRecBArray = Array of TRecB;
  15.  
  16.   TRecC = record
  17.     f1: String;
  18.     f2: String;
  19.     f3: String;
  20.   end;
  21.   TRecCArray = Array of TRecC;
  22.  
  23.   TAllRecs = Record
  24.     RecAs: TRecAArray;
  25.     RecBs: TRecBArray;
  26.     RecCs: TRecCArray;
  27.   end;
  28.  

When I use TAllRecs in a function I SetLength each member on demand to the correct size then fill it up with data and finally return it as the Result.

I keep getting
Quote
Hint: Local variable "AllRecs" of a managed type does not seem to be initialized

FillByte(AllRecs, SizeOf(AllRecs), 0); gives me the same hint

Reading the docs it says I should use AllRecs.create() but that throws an undefined identifier.

This is frustrating...

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Initializing a record containing three dynamic arrays
« Reply #1 on: September 29, 2020, 12:38:31 pm »
This hint is most often annoying rather than helpful when you have specifically allocated a length for a dynamic array.
You can suppress the hint in various ways, such as including
Code: Pascal  [Select][+][-]
  1. {$warn 5091 off}
in your unit.
BTW, if AllRecs is a dynamic array, Sizeof(AllRecs) returns not the length of the array, but the size of the pointer to the array.
You should use SetLength() to initialise dynamic arrays.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Initializing a record containing three dynamic arrays
« Reply #2 on: September 29, 2020, 12:53:25 pm »
@Howardpc warnings are there for a reason!

Anyway:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. type
  3.   TRec = record
  4.     f1: String;
  5.     f2: String;
  6.     f3: String;
  7.   end;
  8.   TRecArray = Array of TRec;
  9.  
  10.   TAllRecs = Record
  11.     RecAs: TRecArray;
  12.     RecBs: TRecArray;
  13.     RecCs: TRecArray;
  14.   end;
  15.  
  16. var
  17. A,B,C:TRec;
  18. D:TAllRecs;
  19. begin
  20.   A:= Default(TRec);
  21.   B:= Default(TRec);
  22.   C:= Default(TRec);
  23.   D:= Default(TAllRecs);
  24. end.
@peardox
Your record structure as you posted above is 3 times the same structure, but to initialize any  record, simply call default() on them.
Ignoring a warning really depends on the situation (e.g. replaced memory manager, local types or vars and such details)
For completeness, it can also be done like this:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}{$modeswitch advancedrecords}
  2. type
  3.   TRec = record
  4.     f1: String;
  5.     f2: String;
  6.     f3: String;
  7.     class operator initialize(var t:Trec);
  8.   end;
  9.   TRecArray = Array of TRec;
  10.  
  11.   TAllRecs = Record
  12.     RecAs: TRecArray;
  13.     RecBs: TRecArray;
  14.     RecCs: TRecArray;
  15.     class operator initialize(var t:TAllRecs);
  16.   end;
  17.  
  18.   class operator TRec.Initialize(var t:TRec);
  19.   begin
  20.     t:= Default(TRec);
  21.   end;
  22.   class operator TAllRecs.Initialize(var t:TAllrecs);
  23.   begin
  24.     t:=Default(TAllRecs);
  25.   end;
  26. begin
  27. end.

This depends on your requirements, since the last example makes the record a managed type.
For simple application I would recommend the first.

« Last Edit: September 29, 2020, 01:08:14 pm by Thaddy »
Specialize a type, not a var.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Initializing a record containing three dynamic arrays
« Reply #3 on: September 29, 2020, 12:54:00 pm »
AllRecs := Default(TAllRecs)?

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Initializing a record containing three dynamic arrays
« Reply #4 on: September 29, 2020, 01:09:55 pm »
AllRecs := Default(TAllRecs)?

Bart
What do you mean? I gave error and warning free examples... I do not think your suggestion is enough, but it would shorten the code for the above question.
In this case that would work, but I suggest to do it on a per record var basis is defensive programming.
Furthermore it does not get rid of the warnings, Bart...
Howardpc hides them, you reintroduce them, I fixed them...
Bad code example:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. type
  3.   TRec = record
  4.     f1: String;
  5.     f2: String;
  6.     f3: String;
  7.   end;
  8.   TRecArray = Array of TRec;
  9.  
  10.   TAllRecs = Record
  11.     RecAs: TRecArray;
  12.     RecBs: TRecArray;
  13.     RecCs: TRecArray;
  14.   end;
  15.  
  16. var
  17. A,B,C:TRec;
  18. D:TAllRecs;
  19. begin
  20.   D:= Default(TAllRecs);
  21.   A:=B;
  22.   B:=C;
  23. end.
Warnings.....:
recinit.pas(22,6) Warning: (5090) Variable "B" of a managed type does not seem to be initialized
recinit.pas(23,6) Warning: (5090) Variable "C" of a managed type does not seem to be initialized.

Now my opinion is to avoid the warnings and not hide them or let them show up. I am a great fan of -Sew  ;) O:-)

« Last Edit: September 29, 2020, 01:22:15 pm by Thaddy »
Specialize a type, not a var.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Initializing a record containing three dynamic arrays
« Reply #5 on: September 29, 2020, 01:17:38 pm »
@Thaddy
Bart's suggestion is all that is required to remove the hint, and initialise a record of type TAllRecs.
Also the compiler is not issuing a warning, but a hint.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Initializing a record containing three dynamic arrays
« Reply #6 on: September 29, 2020, 01:24:20 pm »
Huh? I just demo'd it is a warning....not a hint...  Show me the hint...You did not test, but guessed...
And as usual all three my examples are full programs.
Maybe peardox original mention of the hint is not correct.
Show me a way to reproduce hint instead of warning?
« Last Edit: September 29, 2020, 01:44:01 pm by Thaddy »
Specialize a type, not a var.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Initializing a record containing three dynamic arrays
« Reply #7 on: September 29, 2020, 01:43:57 pm »
@Thaddy, consider this program based on the OP's code:

Code: Pascal  [Select][+][-]
  1. program project1;
  2. type
  3.   TRecA = record
  4.     f1: String;
  5.     f2: String;
  6.     f3: String;
  7.   end;
  8.   TRecAArray = Array of TRecA;
  9.  
  10.   TRecB = record
  11.     f1: String;
  12.     f2: String;
  13.     f3: String;
  14.   end;
  15.   TRecBArray = Array of TRecB;
  16.  
  17.   TRecC = record
  18.     f1: String;
  19.     f2: String;
  20.     f3: String;
  21.   end;
  22.   TRecCArray = Array of TRecC;
  23.  
  24.   TAllRecs = Record
  25.     RecAs: TRecAArray;
  26.     RecBs: TRecBArray;
  27.     RecCs: TRecCArray;
  28.   end;
  29.  
  30. var
  31.   allrecs: TAllRecs;
  32.  
  33. begin
  34.   allrecs := Default(TAllRecs);
  35.   SetLength(allrecs.RecAs, 4);
  36. end.
If you comment out the

Code: Pascal  [Select][+][-]
  1. allrecs := Default(TAllRecs);
line you receive the following hint (it is a hint, not a warning)
Code: Pascal  [Select][+][-]
  1. project1.lpr(36,13) Hint: Variable "allrecs" of a managed type does not seem to be initialized

project1.lpr(36,13) Hint: Variable "allrecs" of a managed type does not seem to be initialized       

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Initializing a record containing three dynamic arrays
« Reply #8 on: September 29, 2020, 01:47:35 pm »
But that is only due to calling setlength() which hides the problem, because setlength re-initializes. That is not a fair argument.
Consider this iteration from your code (and this is not complete, but a fragment for your code);
Code: Pascal  [Select][+][-]
  1. var
  2.   allrecs: TAllRecs =(); // intialized....
  3.  
  4. begin
  5.   //allrecs := Default(TAllRecs);
  6.   SetLength(allrecs.RecAs, 4);
  7. end.
Still warnings...
« Last Edit: September 29, 2020, 01:52:31 pm by Thaddy »
Specialize a type, not a var.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Initializing a record containing three dynamic arrays
« Reply #9 on: September 29, 2020, 02:02:59 pm »
Still warnings...

The only warning that comes here is because you did not initialize the record correctly:

Code: Pascal  [Select][+][-]
  1. var
  2.   allrecs: TAllRecs = (RecAs: Nil; RecBs: Nil; RecCs: Nil); // intialized....
  3.  

No warnings or hints with that.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Initializing a record containing three dynamic arrays
« Reply #10 on: September 29, 2020, 03:01:59 pm »
Yes, I knew that, but OP's question was different and my answers were complete except for your addition. (which is more complex)
The point is to exclude warnings in the code, not hide them as Howard did.. That what I was trying to demonstrate. And the hint is still a mystery to me. 5060 and 5061 seem to be inconsistent.
« Last Edit: September 29, 2020, 03:07:07 pm by Thaddy »
Specialize a type, not a var.

peardox

  • Jr. Member
  • **
  • Posts: 70
Re: Initializing a record containing three dynamic arrays
« Reply #11 on: September 29, 2020, 03:33:02 pm »
Yeah - Default() fixed everything

The records are actually all different - the example was just that, a lazy example to make things shorter

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Initializing a record containing three dynamic arrays
« Reply #12 on: September 30, 2020, 10:06:47 am »
Yes, I knew that, but OP's question was different and my answers were complete except for your addition. (which is more complex)
The point is to exclude warnings in the code, not hide them as Howard did.. That what I was trying to demonstrate.

Then you did not succeed, because your code introduced a new warning:

Code: [Select]
PS D:\fpc\git> fpc -FEtestoutput .\fpctests\thinttest.pp
Free Pascal Compiler version 3.2.0 [2020/07/07] for i386
Copyright (c) 1993-2020 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling .\fpctests\thinttest.pp
thinttest.pp(40,59) Warning: Some fields coming after "" were not initialized
Linking testoutput\thinttest.exe
45 lines compiled, 0.0 sec, 30416 bytes code, 1364 bytes data
1 warning(s) issued

And the hint is still a mystery to me. 5060 and 5061 seem to be inconsistent.

Which messages do you mean? At least in 3.2.0+ 5060 and 5061 are completely different messages.

 

TinyPortal © 2005-2018