Это приведет к утечке памяти? - PullRequest
0 голосов
/ 26 февраля 2011
type
  TTest = class
    a: integer;
  end;
  TTest2 = class(TTest)
    b: integer;
  end;

  var c:TTest;

  begin
    c:=TTest2.Create();
    c.Free;
  end;

Ответы [ 2 ]

8 голосов
/ 26 февраля 2011

Нет, не будет.

Переменная типа базового класса может использоваться для создания экземпляров объектов из ее дочерних классов (они совместимы по типу), но учтите, что при использовании такой переменной вы будете иметь доступ только к членам TTest, но не к TTest2.члены.Это означает;вы можете получить доступ к "a", но не к "b".

Кроме того, если вы столкнулись с каким-либо исключением во время выполнения TTest2.Creation, Create не вернет частично построенный объект.

Однако,если между вызовами TTest2.Create и c.Free есть какие-то другие коды, повышение исключения в этих кодах может вызвать утечку памяти;потому что C.Free не может выполнить.В таком случае вы должны использовать блок try-finally.

5 голосов
/ 26 февраля 2011

Нет, здесь нет утечки памяти.Конструктор возвращает новый ресурс только в случае успеха.Вы можете получить утечку, только если конструктор завершит работу и , если вам не удастся вызвать Free.Поскольку вы ничего не делаете между конструктором и вызовом Free, утечки быть не может.

Если конструктор дает сбой, тогда:

  • Деструктор вызывается для освобождения любогоresources.
  • Возникло исключение.
  • Конструктор не возвращается, поскольку исключение изменяет поток программы.
  • Присваивание переменной объекта, c в вашем примере, не происходит.

Обратите внимание, что ответ от @vcldeveloper, который вы приняли, неверен, когда указано, что nil возвращается.Ничего не возвращается из конструктора, который вызывает.

Вы всегда должны обернуть пары Create / Free парами try / finally следующим образом:

obj := TMyClass.Create;
try
  obj.DoSomething;
finally
  obj.Free;
end;

Вам нужно только защитить ресурс как только он был назначен.Таким образом, вы помещаете try после присваивания.

Если вы поместите try перед конструктором, который является ошибкой:

try
  obj := TMyClass.Create;
  obj.DoSomething;
finally
  obj.Free;
end;

Если конструктор завершится неудачей, тогда objне назначается, а затем, когда Free запускается (и будет работать благодаря finally!), он вызывается для неинициализированной переменной, что приводит к неопределенному поведению.

...