Search code examples
arraysclassinitializationpascal

Pascal - Initializing class variable array


I have a trouble initializing dynamic array in a class. Class looks like this:

MyClass = class
    private
       var
         myVar: array of array of real;
    public
      constructor Create();
      procedure MyMethod(i, j: integer);
end;

Now I'm trying to initialize myVar in MyMethod() (after Create() was called).

procedure MyClass.MyMethod(i, j: integer);
begin
  SetLength(myVar, i, j);
end;

This raises 'Access violation reading from address'. I made sure the integers passed are valid so that is not the problem.

Note that when I try to do the same with local variable it works without an issue. Thanks for help.

Edit:

Since requested, here is whole code. It is an window app that is supposed to load a matrix from a text file, perform a Gaussian elimination and than save it to a text file. Originally I made the question more generic but my problem is with SaveToFile function.

Unit1:

unit Unit1;

{$mode objfpc}{$H+}

interface

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

type

  { TForm1 }

  TForm1 = class(TForm)
    OpenB: TButton;
    SaveB: TButton;
    GaussB: TButton;
    OpenDialog1: TOpenDialog;
    SaveDialog1: TSaveDialog;
    procedure FormCreate(Sender: TObject);
    procedure OpenBClick(Sender: TObject);
    procedure SaveBClick(Sender: TObject);
  private
    M: TMatrix;
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.OpenBClick(Sender: TObject);
var
  path: string;
begin
  if OpenDialog1.Execute()then
  begin
    path:= OpenDialog1.FileName;
    M.LoadFromFile(path);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  M.Create();
end;

procedure TForm1.SaveBClick(Sender: TObject);
var
  path: string;
begin
  if SaveDialog1.Execute then
  begin
    path:= SaveDialog1.FileName;
    M.SaveToFile(path);
  end;
end;

end.

Unit2:

unit Unit2;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils;

type
  TMatrix = class
    private
       var
         matrix: array of array of real;
    public

      constructor Create();
      procedure LoadFromFile(path: string);
      procedure SaveToFile(path: string);
  end;

implementation

constructor TMatrix.Create();
begin

end;

procedure TMatrix.LoadFromFile(path: string);
var
  rows, cols, num, i, j: integer;
  f: TextFile;
begin
  AssignFile(f, path);
  reset(f);

  read(f, rows);
  readln(f, cols);
  SetLength(matrix, rows, cols);

  try
    for i:= 0 to rows - 1 do
    begin
      for j:= 0 to cols - 1 do
      begin
        read(f, num);
        matrix[i, j]:= num;
      end;
      readln(f);
    end;
  except
    raise Exception.Create('Matrix size is incorrect or file is corrupted!');
  end;
  close(f);
end;

procedure TMatrix.SaveToFile(path: string);
var
  num: real;
  i, j: integer;
  f: TextFile;
begin
  AssignFile(f, path);
  rewrite(f);

  for i:= 1 to length(matrix) do
    begin
      for j:= 1 to length(matrix[0]) do
      begin
        num:= matrix[i, j];
        write(f, FloatToStr(num) + ' ');
      end;
      writeln(f);
    end;
  close(f);
end;

end.


Solution

  • Your call to the constructor is

      M.Create();
    

    which is wrong.

    Try this instead:

    M := TMatrix.Create;