Почему я должен привести к определенному типу указателя перед вызовом Dispose? - PullRequest
12 голосов
/ 27 октября 2011

Предположим, у меня есть экземпляр класса 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 () имеет аргумент Pointer, поэтому приведение выглядит глупо, но все же я не уверен в этом. Потому что как функция Dispose () узнает, сколько памяти нужно выделить, когда она получает общий тип Pointer ??

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

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

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

1 Ответ

13 голосов
/ 27 октября 2011

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

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

...