Есть ли, помимо поиска утечек памяти, еще одна ситуация, когда я должен освобождать все объекты при уничтожении приложения?

Предположим, приложение с некоторыми формами и только один модуль данных создается при запуске. В событии DM1.OnCreate создается TStringList для использования во время выполнения. Мы знаем, что при завершении работы приложения все будет уничтожено, а память автоматически освободится. Освобождение чего-либо может занять некоторое время, поэтому не всегда рекомендуется беспокоиться об утечках памяти при завершении работы. См., Например, этот ответ Барри Келли или этот пост от Раймонда Чена.

Кроме того, FastMM сообщает об утечке памяти, если я не добавляю TStringList.Free к DM1.OnDestroy. Это оказывается проблемой при поиске любых других утечек памяти, о которых я должен действительно беспокоиться.

Итак, в основном я спрашиваю, следует ли / почему / когда мне освобождать экземпляры объектов, которые будут освобождены приложением или ОС (Windows в данном конкретном случае). Есть ли другой допустимый случай, которого нет при поиске утечек памяти?

ПРИМЕЧАНИЕ. В этом конкретном случае модуль данных не создается и не воссоздается несколько раз. Никакой утечки памяти, кроме одной, не будет. Источник лома модуля данных:

unit UDM1;

interface

uses SysUtils, Classes, ...;

type
  TDM1 = class(TDataModule)
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
    procedure DoStuffWithStringList1(Sender: TObject);
  private
    internalStL: TStringList;
  end;

var
  DM1: TDM1;

implementation

procedure TDMInterfacePAFECF.DataModuleCreate(Sender: TObject);
begin
  internalStL := TStringList.Create();
end;

procedure TDMInterfacePAFECF.DataModuleDestroy(Sender: TObject);
begin
  internalStL.Free; //<-- IS THIS NECESSARY OR ADVISED?
end;

procedure DoStuffWithStringList(Sender: TObject);
begin
  //Place some code using internalStL here...

end;

person EMBarbosa    schedule 27.03.2012    source источник
comment
ты забыл конец. в конце (: шучу, я всегда освобождаю память, которую выделяю, но это только я, это правда, что Windows освободит ее для вас при выходе из приложения, но также верно и то, что во многих случаях вы никогда не узнаете уверен, как ваше приложение будет вести себя в будущем, поэтому, если вы создаете экземпляр (-ы) в модуле данных Create, было бы разумно (ИМХО) освободить его / их в Destroy, это мои 0,02 доллара (:   -  person    schedule 27.03.2012


Ответы (5)


По той же причине я настоятельно рекомендую (преуменьшение) не оставлять никаких подсказок или предупреждений компилятора в проекте, убирать за собой и НЕ ОСТАВЛЯТЬ СООБЩЕНИЕ ОБ УТЕЧКЕ ПАМЯТИ!
НИКОГДА!

Это не обязательно означает, что вам нужно Освободить все в деструкторе вашего DataModule, если у вас есть веские основания не делать этого, но в этом случае вам необходимо зарегистрировать утечку памяти, чтобы что об этом не будет сообщено. (И поставьте очень заметный комментарий, чтобы обосновать и объяснить почему)

Но учтите тот факт, что вы можете покинуть этот проект, и через год его будет поддерживать кто-то другой и у него появятся новые бизнес-требования по созданию нескольких DataModules ... Скорее всего, если они недостаточно хорошо знают внутреннюю часть вашего кода, они будут полагать, что ваш код чист, и могут возникнуть проблемы.

Поэтому я бы настоятельно не советовал не освобождаться, если только это не особый, ожидаемый и задокументированный случай ...

PS: Я видел это, и мне приходилось столько раз вытирать всю память, капающую повсюду, что я даже провел несколько сессий CodeRage по борьбе с утечками памяти ...

Updayte: вот ссылка для загрузки сеанса CodeRage ...

person Francesca    schedule 27.03.2012
comment
Я принимаю это. В любом случае, для справки в будущем необходимо отметить, что ответ @NGLN показывает способ регистрации ожидаемой утечки памяти. - person EMBarbosa; 10.04.2012
comment
@EMBarbosa, для справки в будущем, я добавил ссылку на сеанс CodeRage; немного устарел, но содержит все еще актуальную информацию (включая регистрацию ожидаемой утечки памяти). :-) - person Francesca; 10.04.2012

Мой ответ можно считать философским, но главная причина в том, что любое действие (или его отсутствие) имеет последствия. Я подумал о вашем примере и, возможно, о других примерах, и вижу одну вескую причину для освобождения объекта. Каждый раз, когда я думаю, что могу проигнорировать освобождение объекта, увеличивается вероятность того, что я этого не сделаю в другой, возможно, более серьезной ситуации. Другой пример - привычка делать «попробуйте, наконец, закончить» везде, где что-то выделяется или освобождается. Я не забочусь об освобождении в случае исключения, но эта привычка помогает мне избежать утечки

person Maksee    schedule 27.03.2012
comment
+1 В приведенном выше примере: что, если в какой-то момент в будущем вы решите повторно использовать свой DM = создать несколько его экземпляров. Каждое создание DM создает TStringList. Каждое уничтожение DM не уничтожает TStringList = Вы как минимум потратили память. Что может даже ухудшиться, если вы сделаете своего DM частью долго работающей службы Windows. Я лично делаю все возможное, чтобы освободить каждый созданный мной объект, чтобы избежать возможных проблем при повторном использовании кода. - person Tom Hagen; 28.03.2012

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

begin
  RegisterExpectedMemoryLeak(TStringList);
  FStringList := TStringList.Create;
  ...

а лучше зарегистрируйте сам указатель:

begin
  FStringList := TStringList.Create;
  RegisterExpectedMemoryLeak(FStringList);
  ...

В этом случае неожиданные утечки памяти проявятся нормально, и их нельзя спутать с этим конкретным списком строк.

person NGLN    schedule 27.03.2012
comment
Но почему это лучше, чем просто освободить объект? Это дольше печатать, труднее понимать, потенциально медленнее, ненужное исключение из обычных правил управления памятью, ... - person jpfollenius; 28.03.2012
comment
@Smasher Да, но OP хочет этого. Как он говорит: Освобождение чего-либо может занять некоторое время. Возможно, список строк не является хорошим примером в этом отношении, но поток , безусловно, может быть. - person NGLN; 28.03.2012
comment
@Smasher На самом деле, если вы увидите две опубликованные мной ссылки, вы обнаружите, что не теряйте время на освобождение чего-то, что будет освобождено, и вовсе не противоречит правилам управления памятью. - person EMBarbosa; 28.03.2012
comment
хорошие ссылки. Я все равно не согласен, может быть, это дело личного вкуса. Для меня намного проще всегда правильно разрушать то, что я создаю. Но, возможно, я передумаю, когда столкнусь с проблемами скорости выключения. - person jpfollenius; 28.03.2012
comment
@Smasher Я тебя понимаю. Я думаю, что это дело личного вкуса, когда замедление не влияет на вас. Поэтому я не сторонник такой реализации, если она вам не нужна. Затем в своих комментариях я просто пытался показать вам, что этого можно было ожидать. Если нет, то для чего была бы создана процедура RegisterExpectedMemoryLeak? Спасибо за ваш комментарий. - person EMBarbosa; 28.03.2012
comment
согласен, есть еще один сценарий для RegisterExpectedMemoryLeak: утечки памяти в коде, который вы не можете изменить (пакеты и т. д.) - person jpfollenius; 28.03.2012

Позвольте мне ответить, задав вам вопрос.

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

Если вы ответите утвердительно, не стесняйтесь игнорировать стандартные методы управления памятью.

Если вы ответите «нет», вы должны убедиться, что объект убирается за собой.

person Kenneth Cochran    schedule 27.03.2012
comment
да. См. Примечание в вопросе. Так вы действительно думаете, что, кроме поиска утечек памяти, нет никакой другой мотивации, чтобы освободить это? - person EMBarbosa; 27.03.2012
comment
Возможно, чтобы избежать закрепления дурной привычки. Я скажу иначе. В тот момент, когда кто-то изменяет код, так что ваше предположение о времени жизни объекта больше не соответствует действительности, возникает реальная утечка памяти. - person Kenneth Cochran; 27.03.2012
comment
Кроме того, в этом примере этого не произойдет, теперь вы сделали хорошее дело. +1 - person EMBarbosa; 27.03.2012

Когда вы освобождаете объект, вся работа выполняется, возможно, больше, чем только освобождение памяти.

На ум приходит объект базы данных, который выполняет транзакции и завершает все запущенные транзакции в ondestroy.

Если вы не позвоните бесплатно, ondestroy не уволят, и вы можете остаться с заблокированными столами.

person Pieter B    schedule 28.03.2012