Let's suppose I have an instance of the TList class (BDS 2006, so this is a list of pointer types). Each pointer I put into the list references memory allocated by the New() function. So when I want to clear the list, I have to iterate through it and dispose each item, right? But how to do that properly? Do I have to cast each disposed item to the actual type it is?
type
TMyRec = record
Field1: string;
Field2: integer;
end;
PMyRec = ^TMyRec;
...
var
MyList: TList;
MyRecPointer: PMyRec;
begin
...
New(MyRecPointer);
...
MyList.Add(MyRecPointer);
...
for i := 0 to MyList.Count - 1 do
Dispose(PMyRec(MyList[x]));
MyList.Clear();
end;
Please look at the for loop at the end. I cast each item to PMyRec to dispose memory. Is that necessary? I know that the Dispose() function has a Pointer argument so casting seems stupid in this case, but still I'm not sure about it. Because how does the Dispose() function know how much memory to dispose when it gets a general Pointer type??
This is a second approach (without type casting):
for i := 0 to MyList.Count - 1 do
Dispose(MyList[x]);
I will be grateful if somebody explains me how it shoud be done and why. Thanks a lot.
There are majorly four types of pointers, they are: Null Pointer. Void Pointer. Wild Pointer. Dangling Pointer.
An IntPtr itself cannot be disposed, because it only represents a location in memory. Your cleanup needs to be specific to the object referred to by the IntPtr . Say you have an unmanaged function that needs a window handle to do its work. In this case you can use the property Control.
C# supports pointers in a limited extent. A C# pointer is nothing but a variable that holds the memory address of another type. But in C# pointer can only be declared to hold the memory address of value types and arrays. Unlike reference types, pointer types are not tracked by the default garbage collection mechanism.
Yes, it's necessary to cast to the proper pointer type. Without that, the RTL doesn't know that the record has a string member, so it won't dispose of the string. It will skip directly to freeing the record's own memory, and the string's contents will leak. It knows how much memory to free for the record the same way FreeMem
knows how much to free from a GetMem
call. The memory manager knows how much memory went to each of its allocations. (There are various ways of keeping track of that.)
Dispose
is a "compiler magic" function. When the compiler sees you call it, it adds a hidden second parameter for the TTypeInfo
record corresponding to the pointer type. That way, the RTL's Dispose
function knows how to process the pointer it receives.
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