What is the difference between System.GetMem and System.ReallocMem?
Delphi 2009 Help for ReallocMem, is exactly the same description of GetMem. How about System.FreeMem and System.Dispose
What should I use with arrays?
type
PMemberDataList = ^TMemberDataList;
TMemberDataList = array[0..MaxClassMembers -1] of PMemberData;
var
FItems: PMemberDataList;
begin
GetMem(FItems, Value * SizeOf(Pointer));
FreeMem(FItems);
end;
or
begin
ReallocMem(FItems, Value * SizeOf(Pointer));
Dispose(FItems);
end;
SOLUTION
After people advices, I declared FItems as record type, not pointer to record, TMemberDataList as dynamic array, SetLength to (de)alloc array, New/Dispose to data
type
PMemberDataList = ^TMemberDataList;
TMemberDataList = array of PMemberData;
var
Items: TMemberDataList;
Item: PMemberData;
// Add
begin
Setlength(Items, 1);
New(Item);
Items[0]:= Item
end;
// Remove
begin
Dispose(Items[0]);
Setlength(Items, 0);
end;
GetMem always allocates memory, FreeMem always releases/frees memory, ReallocMem may do one, the other, or both. In fact, when used properly, ReAllocMem is really the only memory management API needed. If you start with a nil pointer, and call ReAllocMem with a size > 0, then it acts like GetMem. If you call ReAllocMem with size = 0, then it acts like FreeMem. The only time it actually "re-allocates" memory is if the pointer is non-nil and the size > 0.
New and Dispose are designed to work with typed pointers or for you "old-skool" folks, the older Turbo Pascal object model (the old "object) syntax. New and Dispose will also ensure that any typed pointer that is a reference to a managed type will properly initialize that type. For instance given the following:
type
PMyRec = ^TMyRec;
TMyRec = record
Name: string;
Value: Variant;
end;
var
Rec: PMyRec;
begin
New(Rec);
try
Rec.Name := 'TestValue';
Rec.Value := 100;
...
finally
Dispose(Rec);
end;
end;
New and Dispose will ensure that the Name and Value fields of the record are properly initialized and finalized or cleaned-up. New and Dispose, in the above case is equivalent to:
GetMem(Rec, SizeOf(Rec^));
Initialize(Rec);
...
Finalize(Rec);
FreeMem(Rec);
For the example you gave, Gamecat is right, you would probably be better off using a dynamic array since they are better managed by the compiler and they also carry their own intrinsic length. With your example, you would have to separately keep track of the number of items in the array, such that wherever you passed around the array, you'd also have to pass around the currently allocate length. By using a dynamic array, all the information is kept neatly packaged together. This would allow you to iterate over the array regardless of the current length by simply doing one of the following:
var
Member: TMemberData;
Items: array of TMemberData;
...
begin
SetLength(Items, Value);
for Member in Items do // iterate over each element in the array
...
for Low(Items) to High(Items) do // same as above only using std functions
...
end;
Finally, another reason you would probably want to use a dynamic array is that if TMemberData contained strings, variants, interfaces or other "managed" types, they will be properly initialized and finalized without the need to do that manually.
GetMem allocates a block of memory. ReallocMem re-allocates a block of memory.
But you better use dynamic arrays:
var
FItems : array of TMemberDataList;
begin
SetLength(FItems, Value);
end;
Its more the Delphi way.
Example
You could either do:
type
TMemberDataList = array[0..MaxClassMembers -1] of TMemberData;
var
FItems: TMemberDataList;
begin
// Don't need to allocate FItems
end;
Or:
type
TMemberDataList = array of TMemberData;
var
FItems: TMemberDataList;
begin
SetLength(FItems, MaxClassMembers);
end;
Class variables are pointers. So you don't have to use explicit pointers like we had to do with TP. You still can use pointers to records or objects, but there is no reason to do that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With