[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]
{
witold@aed.dsto.gov.au
{--------------------------------------------------------------------------}
Program TestMat(Input,Output);
{ Description: Allocating/deallocating 2D arrays larger than 64kB in size }
{ Date : 12 December 1994 }
{ Author : Witold Waldman }
{ }
{ This is a sample program showing how to go about using the matrix memory }
{ allocation/deallocation functions contained in the unit MATMEM. }
{ }
{ In this example, a two-dimensional array of double precision numbers is }
{ allocated. The total size of the array is chosen to be greater than the }
{ maximum size of a 64kB data segment to illustrate how the techniques }
{ that are implemented here can be used to work with large matrices. }
{ }
{ After the array storage has been created, each element of the array is }
{ filled with a unique number, and the last element in each row is then }
{ displayed on the screen. }
{ }
{ Finally, the array is deallocated and the heap is checked to see if any }
{ memory leaks have occurred. }
{ }
{ Because all memory allocation occurs on the heap at run-time, the use }
{ of extended memory is automatic if the Borland Pascal program is }
{ compiled as a protected mode application. }
{ }
{ The basic idea for the approach used here was taken from a short article }
{ by William F. Polik (PC Tech Journal, December 1986, p. 49). }
{ }
{ Feel free to use this code as you see fit, and I hope that it provides }
{ a useful example of how large arrays can be allocated and accessed from }
{ Turbo Pascal without suffering too greatly from the 64kB segment limit }
{ imposed by the medium memory model used by the compiler. }
{ }
{ NOTE: The source code to the MATMEM unit is located at the bottom of }
{ this program. Just cut and paste it into a separate file. }
{$N+}
{$E+}
{$M 65520,250000,655360 }
Uses CRT,MATMEM;
var
AD : pArrayDD; { Pointer to a two-dimensional array of doubles }
NR : word; { Maximum row dimension of array }
NC : word; { Maximum column dimension of array }
i : word; { Index variable used for traversing rows }
j : word; { Index variable used for traversing columns }
MemBefore : longint; { Memory available before array allocation }
MemAlloc : longint; { Memory available after array allocation }
begin
ClrScr;
{ Configure the size of the 2D matrix we wish to allocate }
NR := 2;
NC := MaxSizeArrayD;
{ Allocate dynamic memory for the 2D array }
MemBefore := MaxAvail;
AD := NewArrayDD(NR,NC);
MemAlloc := MaxAvail;
{ Check to see whether the pointer is nil. If it is, then }
{ the allocation of the array failed. }
If AD = nil then
begin
Writeln('Not enough dynamic memory available for array.');
Halt;
end;
{ Write some info about what was just allocated on the heap }
Writeln('Dynamic memory allocated for array = ',MemBefore-MaxAvail,' bytes');
Writeln;
Writeln('Number of array elements = ',(NR+1)*(NC+1));
Writeln;
{ Proceed to access each element in the array and store a unique number }
{ in each and every array location. Display the value of the last element }
{ in each row of the array for checking purposes. }
For i := 0 to NR do
begin
For j := 0 to NC do
begin
AD^[i]^[j] := j*1.0E0 + i*100000.0E0;
end;
Writeln('Selected array contents: AD^[',i,']^[',NC,'] = ',
AD^[i]^[NC]:10:1);
end;
{ Deallocate dynamic memory for the 2D array }
AD := DisposeArrayDD(AD,NR,NC);
Writeln;
Writeln('Dynamic memory deallocated = ',MaxAvail-MemAlloc,' bytes');
If MaxAvail = MemBefore then
begin
Writeln;
Writeln('No memory leaks detected.');
end
else
begin
Writeln;
Writeln('A memory leak has been detected.');
end;
end.
{---------------------------------------------------------------------------}
{$N+}
{$E+}
UNIT MATMEM;
INTERFACE
const
PtrSize = SizeOf(Pointer);
MaxSegmentSize = 65535;
MaxSizeArrayP = MaxSegmentSize div PtrSize - 1;
MaxSizeArrayR = MaxSegmentSize div SizeOf(Real) - 1;
MaxSizeArrayS = MaxSegmentSize div SizeOf(Single) - 1;
MaxSizeArrayD = MaxSegmentSize div SizeOf(Double) - 1;
MaxSizeArrayI = MaxSegmentSize div SizeOf(Integer) - 1;
type
ArrayPtr = array [0..MaxSizeArrayP] of Pointer;
ArrayR = array [0..MaxSizeArrayR] of Real;
ArrayS = array [0..MaxSizeArrayS] of Single;
ArrayD = array [0..MaxSizeArrayD] of Double;
ArrayI = array [0..MaxSizeArrayI] of Integer;
ArrayRR = array [0..MaxSizeArrayP-1] of ^ArrayR;
ArraySS = array [0..MaxSizeArrayP-1] of ^ArrayS;
ArrayDD = array [0..MaxSizeArrayP-1] of ^ArrayD;
ArrayII = array [0..MaxSizeArrayP-1] of ^ArrayI;
pArrayR = ^ArrayR;
pArrayS = ^ArrayS;
pArrayD = ^ArrayD;
pArrayI = ^ArrayI;
pArrayRR = ^ArrayRR;
pArraySS = ^ArraySS;
pArrayDD = ^ArrayDD;
pArrayII = ^ArrayII;
{ Functions for allocating/deallocating single dimensional arrays. }
{ }
{ NRmax = maximum number of rows allocated/deallocated. }
{ NCmax = maximum number of columns allocated/deallocated. }
function NewArrayS(Nmax:Word):Pointer;
function DisposeArrayS(A:Pointer; Nmax:Word):Pointer;
function NewArrayD(Nmax:Word):Pointer;
function DisposeArrayD(A:Pointer; Nmax:Word):Pointer;
function NewArrayI(Nmax:Word):Pointer;
function DisposeArrayI(A:Pointer; Nmax:Word):Pointer;
function NewArrayR(Nmax:Word):Pointer;
function DisposeArrayR(A:Pointer; Nmax:Word):Pointer;
{ Functions for allocating/deallocating two dimensional arrays. }
{ }
{ NRmax = maximum number of rows allocated/deallocated. }
{ NCmax = maximum number of columns allocated/deallocated. }
function NewArraySS(NRmax,NCmax:Word):Pointer;
function DisposeArraySS(A:Pointer; NRmax,NCmax:Word):Pointer;
function NewArrayDD(NRmax,NCmax:Word):Pointer;
function DisposeArrayDD(A:Pointer; NRmax,NCmax:Word):Pointer;
function NewArrayII(NRmax,NCmax:Word):Pointer;
function DisposeArrayII(A:Pointer; NRmax,NCmax:Word):Pointer;
function NewArrayRR(NRmax,NCmax:Word):Pointer;
function DisposeArrayRR(A:Pointer; NRmax,NCmax:Word):Pointer;
IMPLEMENTATION
{==========================================================================}
function NewArray1D(Nmax:Word; DataSize:Integer):Pointer;
var
MemP : Word;
P : Pointer;
begin
MemP := (Nmax+1)*DataSize;
If MaxAvail >= MemP then
GetMem(P,MemP)
else
P := nil;
NewArray1D := P;
end;
{==========================================================================}
function DisposeArray1D(A:Pointer; Nmax:Word; DataSize:Integer):Pointer;
begin
If A <> nil then
begin
FreeMem(A,(Nmax+1)*DataSize);
DisposeArray1D := nil;
end;
end;
{==========================================================================}
function DisposeArray2D(A:Pointer; NRmax,NCmax:Word; DataSize:Integer):Pointer;
var
I : Word;
Q : ^ArrayPtr;
begin
If A <> nil then
begin
Q := A;
For I := 0 to NRmax do
begin
If Q^[I] <> nil then
FreeMem(Q^[I],(NCmax+1)*DataSize);
end;
FreeMem(A,(NRmax+1)*PtrSize);
DisposeArray2D := nil;
end;
end;
{==========================================================================}
function NewArray2D(NRmax,NCmax:Word; DataSize:Integer):Pointer;
var
Error : Boolean;
I : Word;
MemP : Word; { Memory for pointers to each row of data }
MemR : Word; { Memory for row of data }
P : ^ArrayPtr;
begin
MemP := (NRmax+1)*PtrSize;
If MaxAvail >= MemP then
GetMem(P,MemP)
else
P := nil;
If P <> nil then
begin
Error := false;
MemR := (NCmax+1)*DataSize;
For I := 0 to NRmax do
begin
If MaxAvail >= MemR then
GetMem(P^[I],MemR)
else
begin
Error := true;
P^[I] := nil;
end;
end;
If Error then
begin
P := DisposeArray2D(P,NRmax,NCmax,DataSize);
end;
end;
NewArray2D := P;
end;
{==========================================================================}
function NewArrayS(Nmax:Word):Pointer;
begin
NewArrayS := NewArray1D(Nmax,SizeOf(Single));
end;
{==========================================================================}
function DisposeArrayS(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayS := DisposeArray1D(A,Nmax,SizeOf(Single));
end;
{==========================================================================}
function NewArrayD(Nmax:Word):Pointer;
begin
NewArrayD := NewArray1D(Nmax,SizeOf(Double));
end;
{==========================================================================}
function DisposeArrayD(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayD := DisposeArray1D(A,Nmax,SizeOf(Double));
end;
{==========================================================================}
function NewArrayI(Nmax:Word):Pointer;
begin
NewArrayI := NewArray1D(Nmax,SizeOf(Integer));
end;
{==========================================================================}
function DisposeArrayI(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayI := DisposeArray1D(A,Nmax,SizeOf(Integer));
end;
{==========================================================================}
function NewArrayR(Nmax:Word):Pointer;
begin
NewArrayR := NewArray1D(Nmax,SizeOf(Real));
end;
{==========================================================================}
function DisposeArrayR(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayR := DisposeArray1D(A,Nmax,SizeOf(Real));
end;
{==========================================================================}
function NewArraySS(NRmax,NCmax:Word):Pointer;
begin
NewArraySS := NewArray2D(NRmax,NCmax,SizeOf(Single));
end;
{==========================================================================}
function DisposeArraySS(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArraySS := DisposeArray2D(A,NRmax,NCmax,SizeOf(Single));
end;
{==========================================================================}
function NewArrayDD(NRmax,NCmax:Word):Pointer;
begin
NewArrayDD := NewArray2D(NRmax,NCmax,SizeOf(Double));
end;
{==========================================================================}
function DisposeArrayDD(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArrayDD := DisposeArray2D(A,NRmax,NCmax,SizeOf(Double));
end;
{==========================================================================}
function NewArrayII(NRmax,NCmax:Word):Pointer;
begin
NewArrayII := NewArray2D(NRmax,NCmax,SizeOf(Integer));
end;
{==========================================================================}
function DisposeArrayII(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArrayII := DisposeArray2D(A,NRmax,NCmax,SizeOf(Integer));
end;
{==========================================================================}
function NewArrayRR(NRmax,NCmax:Word):Pointer;
begin
NewArrayRR := NewArray2D(NRmax,NCmax,SizeOf(Real));
end;
{==========================================================================}
function DisposeArrayRR(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArrayRR := DisposeArray2D(A,NRmax,NCmax,SizeOf(Real));
end;
END.
{$N+}
{$E+}
UNIT MATMEM;
INTERFACE
const
PtrSize = SizeOf(Pointer);
MaxSegmentSize = 65535;
MaxSizeArrayP = MaxSegmentSize div PtrSize - 1;
MaxSizeArrayR = MaxSegmentSize div SizeOf(Real) - 1;
MaxSizeArrayS = MaxSegmentSize div SizeOf(Single) - 1;
MaxSizeArrayD = MaxSegmentSize div SizeOf(Double) - 1;
MaxSizeArrayI = MaxSegmentSize div SizeOf(Integer) - 1;
type
ArrayPtr = array [0..MaxSizeArrayP] of Pointer;
ArrayR = array [0..MaxSizeArrayR] of Real;
ArrayS = array [0..MaxSizeArrayS] of Single;
ArrayD = array [0..MaxSizeArrayD] of Double;
ArrayI = array [0..MaxSizeArrayI] of Integer;
ArrayRR = array [0..MaxSizeArrayP] of ^ArrayR;
ArraySS = array [0..MaxSizeArrayP] of ^ArrayS;
ArrayDD = array [0..MaxSizeArrayP] of ^ArrayD;
ArrayII = array [0..MaxSizeArrayP] of ^ArrayI;
pArrayR = ^ArrayR;
pArrayS = ^ArrayS;
pArrayD = ^ArrayD;
pArrayI = ^ArrayI;
pArrayRR = ^ArrayRR;
pArraySS = ^ArraySS;
pArrayDD = ^ArrayDD;
pArrayII = ^ArrayII;
{ Functions for allocating/deallocating single dimensional arrays. }
{ }
{ NRmax = maximum number of rows allocated/deallocated. }
{ NCmax = maximum number of columns allocated/deallocated. }
function NewArrayS(Nmax:Word):Pointer;
function DisposeArrayS(A:Pointer; Nmax:Word):Pointer;
function NewArrayD(Nmax:Word):Pointer;
function DisposeArrayD(A:Pointer; Nmax:Word):Pointer;
function NewArrayI(Nmax:Word):Pointer;
function DisposeArrayI(A:Pointer; Nmax:Word):Pointer;
function NewArrayR(Nmax:Word):Pointer;
function DisposeArrayR(A:Pointer; Nmax:Word):Pointer;
{ Functions for allocating/deallocating two dimensional arrays. }
{ }
{ NRmax = maximum number of rows allocated/deallocated. }
{ NCmax = maximum number of columns allocated/deallocated. }
function NewArraySS(NRmax,NCmax:Word):Pointer;
function DisposeArraySS(A:Pointer; NRmax,NCmax:Word):Pointer;
function NewArrayDD(NRmax,NCmax:Word):Pointer;
function DisposeArrayDD(A:Pointer; NRmax,NCmax:Word):Pointer;
function NewArrayII(NRmax,NCmax:Word):Pointer;
function DisposeArrayII(A:Pointer; NRmax,NCmax:Word):Pointer;
function NewArrayRR(NRmax,NCmax:Word):Pointer;
function DisposeArrayRR(A:Pointer; NRmax,NCmax:Word):Pointer;
IMPLEMENTATION
{==============================================================================
function NewArray1D(Nmax:Word; DataSize:Integer):Pointer;
var
MemP : Word;
P : Pointer;
begin
MemP := (Nmax+1)*DataSize;
If MaxAvail >= MemP then
GetMem(P,MemP)
else
P := nil;
NewArray1D := P;
end;
{==============================================================================
function DisposeArray1D(A:Pointer; Nmax:Word; DataSize:Integer):Pointer;
begin
If A <> nil then
begin
FreeMem(A,(Nmax+1)*DataSize);
DisposeArray1D := nil;
end;
end;
{==============================================================================
function DisposeArray2D(A:Pointer; NRmax,NCmax:Word; DataSize:Integer):Pointer;
var
I : Word;
Q : ^ArrayPtr;
begin
If A <> nil then
begin
Q := A;
For I := 0 to NRmax do
begin
If Q^[I] <> nil then
FreeMem(Q^[I],(NCmax+1)*DataSize);
end;
FreeMem(A,(NRmax+1)*PtrSize);
DisposeArray2D := nil;
end;
end;
{==========================================================================}
function NewArray2D(NRmax,NCmax:Word; DataSize:Integer):Pointer;
var
Error : Boolean;
I : Word;
MemP : Word; { Memory for pointers to each row of data }
MemR : Word; { Memory for row of data }
P : ^ArrayPtr;
begin
MemP := (NRmax+1)*PtrSize;
If MaxAvail >= MemP then
GetMem(P,MemP)
else
P := nil;
If P <> nil then
begin
Error := false;
MemR := (NCmax+1)*DataSize;
For I := 0 to NRmax do
begin
If MaxAvail >= MemR then
GetMem(P^[I],MemR)
else
begin
Error := true;
P^[I] := nil;
end;
end;
If Error then
begin
P := DisposeArray2D(P,NRmax,NCmax,DataSize);
end;
end;
NewArray2D := P;
end;
{==========================================================================}
function NewArrayS(Nmax:Word):Pointer;
begin
NewArrayS := NewArray1D(Nmax,SizeOf(Single));
end;
{==============================================================================
function DisposeArrayS(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayS := DisposeArray1D(A,Nmax,SizeOf(Single));
end;
{==============================================================================
function NewArrayD(Nmax:Word):Pointer;
begin
NewArrayD := NewArray1D(Nmax,SizeOf(Double));
end;
{==============================================================================
function DisposeArrayD(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayD := DisposeArray1D(A,Nmax,SizeOf(Double));
end;
{==============================================================================
function NewArrayI(Nmax:Word):Pointer;
begin
NewArrayI := NewArray1D(Nmax,SizeOf(Integer));
end;
{==============================================================================
function DisposeArrayI(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayI := DisposeArray1D(A,Nmax,SizeOf(Integer));
end;
{==============================================================================
function NewArrayR(Nmax:Word):Pointer;
begin
NewArrayR := NewArray1D(Nmax,SizeOf(Real));
end;
{==============================================================================
function DisposeArrayR(A:Pointer; Nmax:Word):Pointer;
begin
DisposeArrayR := DisposeArray1D(A,Nmax,SizeOf(Real));
end;
{==============================================================================
function NewArraySS(NRmax,NCmax:Word):Pointer;
begin
NewArraySS := NewArray2D(NRmax,NCmax,SizeOf(Single));
end;
{==============================================================================
function DisposeArraySS(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArraySS := DisposeArray2D(A,NRmax,NCmax,SizeOf(Single));
end;
{==============================================================================
function NewArrayDD(NRmax,NCmax:Word):Pointer;
begin
NewArrayDD := NewArray2D(NRmax,NCmax,SizeOf(Double));
end;
{==============================================================================
function DisposeArrayDD(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArrayDD := DisposeArray2D(A,NRmax,NCmax,SizeOf(Double));
end;
{==============================================================================
function NewArrayII(NRmax,NCmax:Word):Pointer;
begin
NewArrayII := NewArray2D(NRmax,NCmax,SizeOf(Integer));
end;
{==============================================================================
function DisposeArrayII(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArrayII := DisposeArray2D(A,NRmax,NCmax,SizeOf(Integer));
end;
{==============================================================================
function NewArrayRR(NRmax,NCmax:Word):Pointer;
begin
NewArrayRR := NewArray2D(NRmax,NCmax,SizeOf(Real));
end;
{==============================================================================
function DisposeArrayRR(A:Pointer; NRmax,NCmax:Word):Pointer;
begin
DisposeArrayRR := DisposeArray2D(A,NRmax,NCmax,SizeOf(Real));
end;
END.
[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]