12

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.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
Mariusz Schimke
  • 3,185
  • 8
  • 45
  • 63

1 Answers1

13

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.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467