Подтвердить что ты не робот

Почему перед вызовом Dispose я должен указать конкретный тип указателя?

Предположим, что у меня есть экземпляр класса TList (BDS 2006, так что это список типов указателей). Каждый указатель, который я помещал в список, ссылается на память, выделенную функцией New(). Поэтому, когда я хочу очистить список, я должен пройти через него и уничтожить каждый элемент, не так ли? Но как это сделать правильно? Должен ли я отбрасывать каждый удаленный элемент до фактического типа?

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;

Пожалуйста, посмотрите на цикл for в конце. Я бросал каждый элемент в PMyRec для утилизации памяти. Это необходимо? Я знаю, что функция Dispose() имеет аргумент указателя, поэтому кастинг кажется глупым в этом случае, но все же я не уверен в этом. Потому что, как функция Dispose() знает, сколько памяти нужно утилизировать, когда она получает общий тип указателя?

Это второй подход (без литья):

for i := 0 to MyList.Count - 1 do
  Dispose(MyList[x]);  

Буду признателен, если кто-нибудь объяснит мне, как это сделать и почему. Большое спасибо.

4b9b3361

Ответ 1

Да, необходимо наложить соответствующий указатель тип. Без этого RTL не знает, что запись имеет член строки, поэтому она не будет удалять строку. Он будет пропускать непосредственно, чтобы освободить запись собственной памяти, и содержимое строки будет протекать. Он знает, сколько памяти освободить для записи тем же способом FreeMem знает, сколько освободится от вызова GetMem. Менеджер памяти знает, сколько памяти пошло на каждое из своих распределений. (Существуют различные способы отслеживания этого.)

Dispose - это "магия компилятора". Когда компилятор видит, что вы его вызываете, он добавляет скрытый второй параметр для записи TTypeInfo, соответствующей типу указателя. Таким образом, функция RTL Dispose знает, как обрабатывать полученный указатель.