Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I have to cast to a specific pointer type before calling Dispose?

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.

like image 305
Mariusz Schimke Avatar asked Oct 27 '11 13:10

Mariusz Schimke


People also ask

What are pointer types in C#?

There are majorly four types of pointers, they are: Null Pointer. Void Pointer. Wild Pointer. Dangling Pointer.

How do you dispose of IntPtr?

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.

Does c sharp have pointers?

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.


1 Answers

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.

like image 87
Rob Kennedy Avatar answered Oct 12 '22 22:10

Rob Kennedy