Bookstore

Recent

Author Topic: SOLVED : type record access violation  (Read 328 times)

Jumbo

  • New Member
  • *
  • Posts: 13
SOLVED : type record access violation
« on: February 16, 2020, 10:26:11 pm »
Using next  code and call te procedure OpenHistory() I get the access violation:

============================================

unit Global;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  fphttpclient, RegExpr;

type
  TForm3 = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
    Procedure OpenHistory();
  end;

type
  SStation = record
    SUrl:String;
    SImg:String;
  end;

var
  G: TForm3;
  History: Array of SStation;

implementation

{$R *.lfm}

Procedure TForm3.OpenHistory();
begin
  // History[0] := SStation. how to make room... //
   History[0].SUrl:='Url';
   History[0].SImg:='Img';
end;

---------------------------------------------

When I call this procedure  I get the access violation.
I call it as G.OpenHistory() and Global is in the uses.... its about just this procedure.
Should I have first done some  new or create for the new record of type History ?

The Compiler likes it but on runtime it fails.

Any help is appreciated. ( I tried a same thing with TstringList, which sould be possible, but that blows my mind totally , even with the lost of examples.)
« Last Edit: February 17, 2020, 01:30:48 pm by Jumbo »

winni

  • Hero Member
  • *****
  • Posts: 1138
Re: type record access violation
« Reply #1 on: February 16, 2020, 10:34:08 pm »
Hi!


Procedure TForm3.OpenHistory();
begin
  SetLength(HIistory,1);

   History[0].SUrl:='Url';
   History[0].SImg:='Img';
end;


Winni

Jumbo

  • New Member
  • *
  • Posts: 13
Re: type record access violation
« Reply #2 on: February 17, 2020, 01:30:15 pm »
Silly I could not find that,  Winni, thanks for the answer!

No create, no new ... just increase the number of records.
It seems to work, but I have no idea why....

Now the code is:

....
begin
   Cnt:= Length(History);
   Log('Cnt : '+ IntToStr(Cnt));
   SetLength(History,Cnt+1);
   History[Cnt].SUrl:='Url';
 ...
...   

Works as a charm...

Thaddy

  • Hero Member
  • *****
  • Posts: 9809
Re: SOLVED : type record access violation
« Reply #3 on: February 17, 2020, 03:27:16 pm »
In 3.2.0 there is another syntax to achieve this, see:https://wiki.freepascal.org/FPC_New_Features_3.2#Dynamic_Arrays_have_built_in_.2B_operator_support
Example:
Code: Pascal  [Select]
  1. {$mode delphi}{$H+}
  2. type
  3.   SStation = record
  4.     SUrl:String;
  5.     SImg:String;
  6.   end;
  7.  
  8. var
  9.   History: Array of SStation =[]; // initialized dynamic array
  10.   S:SStation;
  11. begin
  12.   // Fill a record
  13.   S.Surl :='http://example.com';
  14.   S.Simg:='img';
  15.   // And simply add it, does not need setlength
  16.   History := History + [S];
  17.   // Add another
  18.   S.Surl :='http://www.example.com';
  19.   S.Simg:='img2';
  20.   History := History + [S];
  21.   // Show records in History
  22.   for S in History do writeln(S.Surl,sLineBreak,S.SImg);
  23. end.
Just for completeness.
I am more like donkey than shrek

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: type record access violation
« Reply #4 on: February 17, 2020, 03:30:10 pm »
It seems to work, but I have no idea why....

When you declare a dynamic array (an array of sometype) variable there is no way for the compiler to guess how it'll be used or how much space to reserve for it, so it just makes a note that such a variable exists and assigns a null pointer for it. If you then try use that variable before "constructing" the array the operation means basically dereferencing a null pointer, which of course causes an access violation.

Only when you SetLength to the array this happens (very basically!): some memory is reserved for X items and the var is made to point to that newly allocated block. From then on you can safely use the array items for whatever you want. But take care! If you try to address items beyond the assigned length it will fail again: you must grow (or diminish) your array as needed.

Note also that by this same rule, setting the array's length to 0 (zero) will deallocate any memory assigned to it and revert back to the starting point and, IIRC, the "pointer" will again be Nil.

HTH
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.