Что происходит с объектом, выпадающим из области видимости в Delphi? - PullRequest
4 голосов
/ 11 марта 2009

Когда объект, созданный внутри функции и функции завершен, что происходит с объектом, если он не был явно уничтожен?

Нужно ли уничтожать все переменные, когда они выпадают из области видимости, или о них заботятся, когда они выпадают из области видимости?

Так, например, что происходит с locallist после вызова custom_function?

function TForm1.custom_function(string: test_string): boolean;
var locallist: TStringList;
begin
  locallist := TStringList.Create;
  // do a bunch of stuff here, but don't destroy locallist
  return true;
end;

Ответы [ 5 ]

16 голосов
/ 11 марта 2009

Вы получите утечку памяти.

Правильный шаблон

myObject := TObject.Create;
try
  //do stuff
finally
  myObject.Free;
end;

Также, если вам нужно позже проверить, был ли объект освобожден, используйте FreeAndNil (myObject). Он также установит для переменной значение nil, так что вы можете проверить это позже.

11 голосов
/ 12 марта 2009

Как отмечали другие авторы, эти объекты должны быть явно освобождены. Обычно это делается вручную с помощью блока try..finally, как продемонстрировал Рэй. Однако есть исключения, о которых вам следует знать.

Компоненты (потомки TComponent) передают параметр Owner своему конструктору. Если владельцем не является nil , то компонент-владелец станет владельцем нового компонента и освободит его при освобождении. Вот почему вам не нужно очищать свои собственные формы; они связаны с объектом Application, который знает, как освободить себя , когда программа будет завершена. Однако, если вы создаете компонент во время выполнения, вам нужно либо назначить его владельцем, либо передать конструктору nil , а затем освободить его самостоятельно. Не смешивайте их, освобождая компонент с владельцем. Это может привести к условию двойного освобождения при определенных обстоятельствах.

Интерфейсные объекты, которые реализуют подсчет ссылок (в основном потомки TInterfacedObject) освобождаются механизмом подсчета ссылок, если вы ссылаетесь на них именно как на интерфейс (а не на объект). Они освобождаются автоматически, когда последняя ссылка на них имеет интерфейс удален. Не освобождайте TInterfacedObject вручную, если вы уже присвоили ему ссылку на интерфейс. Это вызовет исключение. Также следует помнить, что не все объекты с интерфейсами реализуют подсчет ссылок. В основном только те, которые произошли от TInterfacedObject.

Не всегда практично создавать объект, использовать блок try..finally, а затем освобождать его. Иногда это просто не работает для того, что вы делаете, особенно если вы присваиваете объект какому-то списку (и создаете их очень много). В этом случае хорошей идеей является использование TObjectList ( или еще лучше, если у вас D2009, TObjectList) со свойством OwnsObjects, установленным в true . Это приводит к тому, что список становится владельцем объектов в нем и освобождает их, когда он освобождается, как это делают компоненты. Опять же, не освобождайте объект вручную, если он принадлежит списку объектов.

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

Возможно, это звучит сложно, но вы скоро к этому привыкнете. Просто помните, что каждый объект принадлежит одной из трех вещей: другому объекту, системе подсчета ссылок интерфейса или вашему коду, и владелец должен освободить все его объекты, когда они больше не нужны. Ничто не должно пытаться освободить то, что принадлежит кому-то другому. (Не укради.) Запомни эти рекомендации, и у тебя получится хорошее управление памятью. Вы также можете установить «ReportMemoryLeaksOnShutdown: = true» в основной подпрограмме в DPR для получения дополнительной помощи.

5 голосов
/ 11 марта 2009

становится утечка памяти.

Обычно вы должны окружать такие выделения следующим образом:

locallist := TStringList.Create;
try
     // work with locallist here
  finally
     locallist.Free;
  end; 

Единственными ссылками в Delphi, которые самоубийственны, когда выпадают из области видимости, являются ссылки на интерфейсы.

3 голосов
/ 11 марта 2009

Это приведет к утечке памяти , которая будет уничтожена только в конце приложения. Чтобы обнаружить их, вы можете использовать менеджер памяти, такой как FastMM .

Обратите внимание, что вы можете уничтожать объекты, используя метод Destroy или Free. Первый из них выдаст ошибку, если объект равен нулю, последний - нет - он равен

if Assigned(Object) then Object.Destroy;
3 голосов
/ 11 марта 2009

Память не исправлена, извините. Вам необходимо явно освободить этот объект, используя locallist.Free;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...