Recent

Author Topic: Will someone please enlighten me on this?  (Read 726 times)

scasparz

  • Jr. Member
  • **
  • Posts: 55
Will someone please enlighten me on this?
« on: November 29, 2022, 12:16:10 am »
Am Linux Mint on the latest Lazarus. Please consider the following simplified code:

Code: Pascal  [Select][+][-]
  1. CONST
  2.   MaxElement = 9;
  3.  
  4. type
  5.   tTypes = String;
  6.   tStructures = RECORD
  7.                   Int: Integer;
  8.                   Typ: tTypes
  9.                 END;
  10.  
  11.   tpArrays = ^tArrays;
  12.   tArrays  = ARRAY [0..MaxElement] OF tStructures;
  13.  
  14.   { TForm1 }
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     procedure Button1Click(Sender: TObject);
  18.   private
  19.   public
  20.     ApArray: tpArrays;
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27. {$R *.lfm}
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.Button1Click(Sender: TObject);
  32. CONST
  33.   ElementCount = 2;
  34.  
  35. begin
  36.   GetMem(ApArray, ElementCount * SizeOf(tStructures)); // (0)
  37.  
  38.   ApArray^[0].Int := 0;
  39.   ApArray^[0].Typ := 'zero'; // (1) on D7 it breaks here with 'Access violation at address 0403ECE in module project1.exe. Read of address 00000004'. Process stopped.
  40.  
  41.   ApArray^[1].Int := 1;
  42.   ApArray^[1].Typ := 'one'; // (2) on Laz for windows (v2.0.2) it breaks here with 'Project project1 raised exception class 'External SIGEGV'. At address 403A61
  43.  
  44.   ShowMessage(Format('%s, %s', [ApArray^[0].Typ, ApArray^[1].Typ]))
  45. end;
  46.  

On Laz v2.0.2 on XPs will break at sentence (2).

On Linux, sometimes it runs, others it does not. When it does not, it breaks on the same sentence (2).

On an old D7 again on XPs will break at sentence (1); Am not interested on D7, I just tried this to satisfy my curiosity.

Will work smoothly on all platforms if I replace declaration of tTypes with anything else, say a shortstring.
Also will run smoothly if I replace (0) with New(ApArray);

Is my understanding I could use an open Array, however am puzzled why this does not work. What am I doing wrong mates?



cheers
s

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: Will someone please enlighten me on this?
« Reply #1 on: November 29, 2022, 01:16:44 am »
Code: Pascal  [Select][+][-]
  1.   GetMem(ApArray, ElementCount * SizeOf(tStructures)); // (0)

The error probably depends on "string" being ansi- or short-string.

This looks like a normal Lazarus project, and likely contains a {$H+} => use ansistring.

https://www.freepascal.org/docs-html/rtl/system/getmem.html
Quote
The newly allocated memory is not initialized in any way
And this then can be affected by
- the OS
- the mem manager your app uses (default, cmem, heaptrc

In any case the memory contains just random bytes.

An ansistring is a pointer to internally managed data. That data must be initialized. If the ansistring-pointer is random data, then it expects this to point to valid-(string-)initialized memory...
Well and it  does not, it point somewhere random.


And Btw, if you get zero filled mem, and you put ansistring in there like this, and you FreeMem the array => memory leak.




jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Will someone please enlighten me on this?
« Reply #2 on: November 29, 2022, 02:24:28 am »
How about taking the CARET out of it?

apArray[0].Int....

etc.

The only true wisdom is knowing you know nothing

scasparz

  • Jr. Member
  • **
  • Posts: 55
Re: Will someone please enlighten me on this?
« Reply #3 on: November 29, 2022, 03:03:40 am »
Many thanks to both of you for your input.

@Martin_fr
Good point mate. ApArray is allocated memory with (0), therefore I would expect that statements (1) and (2) are executed on available memory rather than on some arbitrary memory chunk. Given the Typ field is actually a pointer as well, I have tried to have it initialized with SetLength, just to ensure there is memory for them either, this am afraid had no impact.
Replacing the array of pointers with an Open Array, that is instead of using
Code: Pascal  [Select][+][-]
  1. ApArray: tpArrays;
  2. // use this
  3. AArray: ARRAY OF tStructures;
  4.  
IMO this works flawlessly on all platforms even with D7. Much like by replacing GetMem with New.
In case this is a memory manager issue, have not changed the one I use on any platforms, expect this to be the std.
Have tried heaptrc on Linux and app does not work. Works with cmem though. cmem does not work on XPs.
Looks like it is not a memory manager issue.

@jamie Have followed your advice, did not work either on D7 nor on Laz over XPs

Still confused mates.


s
« Last Edit: November 29, 2022, 03:33:38 am by scasparz »

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Will someone please enlighten me on this?
« Reply #4 on: November 29, 2022, 08:25:32 am »
Works
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. CONST
  3.   MaxElement = 9;
  4.  
  5. type
  6.   tTypes = String;
  7.   tStructures = RECORD
  8.                   Int: Integer;
  9.                   Typ: tTypes
  10.                 END;
  11.   tArrays  = ARRAY [0..MaxElement] OF tStructures;
  12.   tpArrays = ^tArrays;
  13.  
  14. var
  15.   ApArray: tpArrays;
  16.  
  17.  
  18. procedure Test;
  19. //CONST
  20.   //ElementCount = 2;
  21.  
  22. begin
  23.   new(ApArray);
  24.  
  25.   ApArray^[0].Int := 0;
  26.   ApArray^[0].Typ := 'zero'; // (1) on D7 it breaks here with 'Access violation at address 0403ECE in module project1.exe. Read of address 00000004'. Process stopped.
  27.  
  28.   ApArray^[1].Int := 1;
  29.   ApArray^[1].Typ := 'one'; // (2) on Laz for windows (v2.0.2) it breaks here with 'Project project1 raised exception class 'External SIGEGV'. At address 403A61
  30.  
  31.   //ShowMessage(Format('%s, %s', [ApArray^[0].Typ, ApArray^[1].Typ]))
  32.   Dispose(ApArray);
  33. end;
  34.  
  35. Begin
  36.   Test;
  37. End.
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Will someone please enlighten me on this?
« Reply #5 on: November 29, 2022, 12:51:14 pm »
Its coder errors.

Your pointer is looking at the wrong type.

I am sure you will figure it out... ;)
The only true wisdom is knowing you know nothing

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Will someone please enlighten me on this?
« Reply #6 on: November 29, 2022, 12:52:35 pm »
If you use raw (untyped) memory allocation you need to call initialize and finalize on the (typed) data before using:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. CONST
  3.   ElementCount = 2;
  4.  
  5. begin
  6.   GetMem(ApArray, ElementCount * SizeOf(tStructures)); // (0)
  7.   Initialize(ApArray^[0]);
  8.   ApArray^[0].Int := 0;
  9.   ApArray^[0].Typ := 'zero'; // (1) on D7 it breaks here with 'Access violation at address 0403ECE in module project1.exe. Read of address 00000004'. Process stopped.
  10.  
  11.   Initialize(ApArray^[1]);
  12.   ApArray^[1].Int := 1;
  13.   ApArray^[1].Typ := 'one'; // (2) on Laz for windows (v2.0.2) it breaks here with 'Project project1 raised exception class 'External SIGEGV'. At address 403A61
  14.  
  15.   ShowMessage(Format('%s, %s', [ApArray^[0].Typ, ApArray^[1].Typ]))
  16.  
  17.   // Finalization
  18.   Finalize(ApArray^[0]);
  19.   Finalize(ApArray^[1]);
  20.   FreeMem(ApArray);
  21. end;

Also if you are in Mode ObjFPC you don't need this weird pointer to static max size array construct, you can just use element pointers:
Code: Pascal  [Select][+][-]
  1. type
  2.   tTypes = String;
  3.   tpStructures = ^tStructures;
  4.   tStructures = RECORD
  5.                   Int: Integer;
  6.                   Typ: tTypes
  7.                 END;
  8.  
  9. var
  10.   ApArray: tpStructures;
  11.  
  12. procedure TForm1.Button1Click(Sender: TObject);
  13. CONST
  14.   ElementCount = 2;
  15.  
  16. begin
  17.   GetMem(ApArray, ElementCount * SizeOf(tStructures)); // (0)
  18.   Initialize(ApArray[0]);
  19.   ApArray[0].Int := 0;
  20.   ApArray[0].Typ := 'zero'; // (1) on D7 it breaks here with 'Access violation at address 0403ECE in module project1.exe. Read of address 00000004'. Process stopped.
  21.  
  22.   Initialize(ApArray[1]);
  23.   ApArray[1].Int := 1;
  24.   ApArray[1].Typ := 'one'; // (2) on Laz for windows (v2.0.2) it breaks here with 'Project project1 raised exception class 'External SIGEGV'. At address 403A61
  25.  
  26.   ShowMessage(Format('%s, %s', [ApArray[0].Typ, ApArray[1].Typ]))
  27.  
  28.   // Finalization
  29.   Finalize(ApArray[0]);
  30.   Finalize(ApArray[1]);
  31.   FreeMem(ApArray);
  32. end;

scasparz

  • Jr. Member
  • **
  • Posts: 55
Re: Will someone please enlighten me on this?
« Reply #7 on: December 02, 2022, 06:05:23 am »
Many thanks Warfley for pointing me to the right direction, your code solved the issue.
Have done some search and now I even know why (the RTTI thing).
Just for the rec, am old school, I prefer the caret notation.



kind regards
s

 

TinyPortal © 2005-2018