Свободная память и ноль в Delphi с помощью единственной функции

У меня есть много выделений памяти и то же количество вызовов FreeMem. Что я не имел, хотя проверка перед звонящими почетными гражданами, чтобы видеть, был ли указатель нолем и строкой после освобождения для установки указателя на ноль.

Я пытался создать функцию, чтобы сделать это

procedure FreeMemAndNil(p: Pointer; size: Integer = -1);
begin
  if p <> nil then
  begin
    if size > -1 then
      FreeMem(p, size)
    else
      FreeMem(p);
    p := nil;
  end;
end;

Но существует проблема. Это не может установить origional указатель на ноль, потому что параметр не является переменным (var p: Указатель). Я не могу использовать var, хотя, потому что, если я, компилятор жалуется, тип должен быть тем же самым типом (Указатель). Указатели я являюсь передающим, могли быть указателями на любой тип (PChar, регулярный указатель, и т.д.).

Что я могу сделать для фиксации этого? Существует ли лучшее решение?

8
задан Daisetsu 11 August 2010 в 18:56
поделиться

4 ответа

Подобно Мейсон Уиллер сказал, что вы должны использовать тот же трюк, что и FreeAndNil в модуле SysUtils для ссылок на объекты.
Итак, я изменил ваш код, проверил его, и он отлично работает:

procedure FreeMemAndNil(var ptr; size: Integer = -1);
var
  p: Pointer;
begin
  p := Pointer(ptr);
  if p <> nil then
  begin
    if size > -1 then
      FreeMem(p, size)
    else
      FreeMem(p);
    Pointer(ptr) := nil;
  end;
end;

- jeroen

PS: Роб Кеннеди написал хороший ответ на нетипизированные параметры var , в котором есть ссылка на его нетипизированный параметр страница в Интернете.

PS2: Для справки: Kylix-версия SysUtils.pas находится в интерактивном режиме , а FreeAndNil там идентичен тому, как он находится в Delphi.

6
ответ дан 5 December 2019 в 05:18
поделиться

В SysUtils есть процедура под названием FreeAndNil, которая делает это для объектов. Он делает это с помощью нетипизированного параметра var , который он преобразует в TObject, и вы должны убедиться, что вы не передали ему что-то, кроме TObject. Вы можете сделать что-то подобное здесь, если вам нужно. Просто будь осторожен; если вы это сделаете, безопасности типов не будет.

9
ответ дан 5 December 2019 в 05:18
поделиться

Я часто работаю с ReallocMem для работы с указателями/памятью.

Вызов

ReallocMem(P,0)

установит указатель в Nil.

1 вещь, которую вам нужно знать об использовании этой функции, P должен быть инициализирован перед передачей в ReallocMem.

.
4
ответ дан 5 December 2019 в 05:18
поделиться

Чтобы иметь возможность передавать произвольные значения указателя в эту функцию, вам необходимо следовать той же модели, что и FreeAndNil, и передавать нетипизированный параметр . В противном случае компилятор правильно жалуется на несовпадение фактических и формальных типов параметров. Приведите нетипизированный параметр к Pointer, когда вы вызываете для него FreeMem.

В этой функции вы делаете пару бессмысленных вещей.

Прежде всего, освобождение нулевого указателя всегда безопасно, поэтому нет причин проверять это перед вызовом FreeMem. Это освобождает указатель, отличный от nil, о котором вам нужно беспокоиться, но никакая функция не защитит вас от этого.

Далее, параметр размера FreeMem в течение многих лет игнорировался. Раньше считалось, что если вы предоставляли этот параметр, он должен был соответствовать размеру, переданному в GetMem, но в настоящее время FreeMem полностью игнорирует этот параметр - компилятор даже не передает этот параметр функции.

Учитывая все вышесказанное, ваша функция сводится к следующему:

procedure FreeMemAndNil(var P);
var
  Tmp: Pointer;
begin
  Tmp := Pointer(P);
  Pointer(P) := nil;
  FreeMem(Tmp);
end;

Будьте осторожны, чтобы случайно не вызвать эту функцию для всего, что не указатель, выделенный с помощью GetMem. Компилятор не поймает это за вас, как если бы вы использовали типизированные параметры. Если вы попытаетесь освободить что-то, что не было выделено с помощью GetMem, вы, вероятно, получите исключение EInvalidPointer, но переменная, которую вы передали, после этого все равно будет равна нулю. Таким же образом работает FreeAndNil.

13
ответ дан 5 December 2019 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: