arrayspointersmultidimensional-arraymemory-managementfreepascal

Error while deleting 3D dynamic array in FreePascal


The point is to make it work with pointers. Also, I found similar problem with C++. It’s not working in FreePascal, well, I probably missed something.

  1. I declare types and variable for my pointers:
    type
      PReal = ^double;
      PPReal = ^PReal;
    var
      data : ^PPReal;
    
  2. This is how I allocate memory (x, y, and z are dimensions):
    GetMem( data, sizeof(PPReal)*x );
    for i:=0 to x-1 do begin
      GetMem( (data+i)^, sizeof(PReal)*y );
      for j:=0 to y-1 do begin
        GetMem( ((data+i)^+j)^, sizeof(real)*z );
      end;
    end;
    
  3. And this is how I try to Dispose it:
    for i:=0 to x-1 do begin
      for j:=0 to y-1 do begin
        Dispose( ((data+i)^+j) );
      end;
      Dispose( (data+i) );
    end;
    Dispose( data );
    

However, I’m getting 216 (memory access) or 204 (invalid pointer operation) runtime errors. Like this:

Enter X, Y, Z size: 
2 2 2
 
0 0 *
0 1 *
0 1
1 0 *
1 1 *
Runtime error 216 at $00404ED5
  $00404ED5
  $004078A1
 
Enter X, Y, Z size: 
1 1 2
 
0 0 *
0 0
Runtime error 204 at $00404DFB
  $00404DFB
  $004078A1
 
Enter X, Y, Z size: 
3 2 1
 
0 0 *
0 1 *
0 1
1 0 *
1 1 *
Runtime error 216 at $00404ED5
  $00404ED5
  $004078A1

Full code (FreePascal IDE):

program test;
type
  PReal = ^double;
  PPReal = ^PReal;
var
  x,y,z : integer;
  i,j,k : integer;
  data : ^PPReal;
begin
    writeln('Enter X, Y, Z size: ');
    read(x,y,z);
 
    GetMem( data, sizeof(PPReal)*x );
    for i:=0 to x-1 do begin
      GetMem( (data+i)^, sizeof(PReal)*y );
      for j:=0 to y-1 do begin
        GetMem( ((data+i)^+j)^, sizeof(real)*z );
      end;
    end;
 
    for i:=0 to x-1 do begin
      for j:=0 to y-1 do begin
        writeln(i,' ',j,' *');
        Dispose( ((data+i)^+j) );
      end;
      writeln(i,' ',j);
      Dispose( (data+i) );
    end;
    Dispose( data );
end.

Solution

  • The last dispose is mirrored to its getmem, but the other two not. Fix that and it works:

      for i:=0 to x-1 do begin
        for j:=0 to y-1 do begin
        writeln(i,' ',j,' *');
        Dispose( ((data+i)^+j)^ );
      end;
      writeln(i,' ',j);
      Dispose( (data+i)^ );
    end;
    Dispose( data );
    

    p.s. freemem is the logical companion to getmem, as dispose is to new.