'How to fix an External: ACCESS VIOLATION error in Pascal?

I'm getting an error in Pascal, and according to my research it's due to a declaration error (class or variable). It has to be something small, since it was working just fine. I would really appreciate any help.

To be more specific, the error I'm getting is:

'External:ACCESS VIOLATION' with message: Accedd violation reading from address $000004A8. In line 66: Efa.Text:=D.Fa ;

unit UnidadProyectoInformaticaUno;

{$mode objfpc}{$H+}{$R+}{$Q+}

interface

uses
   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,Math;

type

{ TForm1 }

TForm1 = class(TForm)
   BNext: TButton;
   BPrev: TButton;
   BAdd: TButton;
   BDel: TButton;
   BClose: TButton;
   EFa: TEdit;
   EIm: TEdit;
   EOch: TEdit;
   EOt: TEdit;
   ENum: TEdit;
   LabFa: TLabel;
   LabIm: TLabel;
   LabOch: TLabel;
   LabOt: TLabel;
   LabNUM: TLabel;

   procedure BAddClick(Sender: TObject);
   procedure BCloseClick(Sender: TObject);
   procedure BDelClick(Sender: TObject);
   procedure BNextClick(Sender: TObject);
   procedure BPrevClick(Sender: TObject);


   private

   public

   end;

   var
      Form1: TForm1;

   implementation

   {$R *.lfm}
   type
      R= record
         Fa,Im,Och: string[20];
         Ot:array[1..5] of integer;
      end;
   Var F:file of R;
      D,D1,D2:R;
      Irec,i,j,k:integer;
      note,grade,nada:string;

   procedure OutRec;
   begin
      with Form1 do
      IF Irec > 0 then
      begin
           seek(F,Irec-1);
           read(F,D);
           EFa.Text:=D.Fa;
           EIm.Text:=D.Im;

           for i:= 1 to 5 do
              begin
                 grade:= grade +IntToStr(D.Ot[i])+' ';
              end;

           Eot.Text:=grade;
           EOch.Text:=D.Och;
           Enum.Text:= IntToStr(Irec);

      end
      else
      begin
         EFa.Text:=nada;
         Enum.Text:=nada;
      end;
   end;

   { TForm1 }

   procedure TForm1.BNextClick(Sender: TObject);
   begin
      If Irec = filesize(F) then
      Exit
      else
      Irec:= Irec+1;
      OutRec;
   end;

   procedure TForm1.BAddClick(Sender: TObject);
   begin
      D.Fa:=Efa.Text;
      D.Im:=Eim.Text;
      D.Och:=EOch.Text;
      Note:= Eot.text;
   for i:= 1 to 5 do
       begin
          k:=Pos(' ',Note);
          D.Ot[i]:= strToInt(Copy(Note,1,k-1));
          Delete(Note,1,k);
       end;

   seek(F,FileSize(F));
   Write(F,D);
   Irec:= FileSize(F);
   OutRec;
 end;

 procedure TForm1.BCloseClick(Sender: TObject);
 begin
     close
 end;

 procedure TForm1.BDelClick(Sender: TObject);
 begin
 for i:= Irec+1 to Filesize(F) do
    begin
    seek(F,i-1);
    read(F,D);
    Seek(F,i-2);
    Write(F,D);
end;

Seek(F,Filesize(f)-1);
   Truncate(F);
   Irec:= Min(Irec,FileSIze(F));
   Outrec;
end;

procedure TForm1.BPrevClick(Sender: TObject);
   begin
   if Irec<2 then Exit;
   Irec:= Irec-1;
   OutRec;
end;

function Sort(Z:R):string;
begin
     Result:=Z.Fa+' '+Z.Im+' '+Z.Och;
end;

procedure  BStatus;
    begin
    with Form1 do
    BNext.Enabled:= Irec < FileSize(f);
end;

procedure  B1Status;
    begin
    with Form1 do
    BPrev.Enabled:= Irec > 1;
end;

procedure  B2Status;
    begin
    with Form1 do
    BAdd.Enabled:= length(Eot.Text) > 0 ;
end;

procedure  B3Status;
    begin
    with Form1 do
    BDel.Enabled:= IRec > 0;
end;

begin

assignfile(F,'file.dat');
    try reset(F);
    except
    rewrite(F);
end;

Irec:= Min(1,filesize(F));
OutRec;


for i :=1 to filesize(F)-1 do
  for j:= Filesize(F) to i  do
  begin
     seek(F,i);
     read(F,D1,D2);
     if Sort(D1)>Sort(D2) then
  begin

  write(f,D2,D1);
  end;

  end;
end.


Solution 1:[1]

In Free Pascal Reference guide, version 3.04 (May 2018), Paragraph 16.2 that deals with Units, it is said that a unit may have an initialization part and a finalization part. It is also said: "An initialization section by itself (i.e. without finalization) may simply be replaced by a statement block.", which is what you have in your code.

That statement block, between the begin and end of the unit, executes at program initialization before the Form1 (declared in the same unit) is created. Therefore you can not refer to anything belonging to the form, like fields, controls, methods, etc. in this statement block, neither directly nor indirectly.

You are calling procedure OutRec, which refers to Efa: TEdit of the form. Since the form is not yet created, you get the error of Access violation.

You must rearrange your code so it doesn't attempt to access any parts of the form from the statement block that replaces a unit initialization part.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1