2009-03-11 3 views
4

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

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

Так, например, что происходит с 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; 

ответ

16

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

Правильная картина

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

Кроме того, если вам необходимо проверить позже, если объект был освобожден, а затем использовать FreeAndNil (MyObject). Он также установит переменную в нуль, чтобы вы могли ее протестировать позже.

5

Это утечка памяти.

Вы должны, как правило, окружают такие распределения, таким образом:

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

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

+0

и ссылки на строки и ссылки на интерфейс –

+0

Создается перед попыткой. Всегда. – Ray

+0

Если вы используете это, вы получите предупреждения для каждого объекта, так как возможно, что создание не удастся, и тогда объект попытается освободиться. – Ray

3

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

3

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

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

if Assigned(Object) then Object.Destroy; 
+0

Итак, что такое FastMM-инструмент, который скомпилирован в приложение или это какой-то тип надстройки для редактора/компилятора Delphi? – Dave

+0

Он скомпилирован в приложение. Вы добавляете его в предложения использования, и он добавляется в ваш проект. Он имеет два эффекта: 1. Ускорение работы с памятью Delphi, 2. Обнаружение утечек памяти. Утечки утечки сообщаются с трассировкой стека при запуске проекта в компиляторе. – schnaader

+0

Я подумал, что FastMM был включен в более поздние версии Delphi (ну, тем не менее, ускоряющая часть). Я могу ошибаться. – Ray

10

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

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

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

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

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

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

+1

«Не смешивайте их, освобождая компонент вместе с владельцем, что приведет к условию двойного освобождения». Можем ли мы прекратить повторять это? Это просто неправильно. Освобождение компонента с владельцем удалит его из списка принадлежащих ему компонентов. Он может быть субоптимальным или запутанным ... – mghie

+0

, но это не неправильно или опасно. Для получения дополнительной информации см. Http://stackoverflow.com/questions/398137. Это вычитает из вашего хорошего ответа. – mghie

+0

Зависит от того, как это делается. Это один бит меня один раз, когда у меня был код, который пытался освободить компонент, который я создал * после того, как * форма, которая принадлежала ему, была уничтожена. (Да, это не обычное условие, но это может произойти, если вы не будете осторожны.) Но я немного его отредактирую ... –

Смежные вопросы