Почему TObject.Free вызывается перед выполнением первой строки кода моего приложения? - PullRequest
1 голос
/ 17 марта 2011

Мы пытаемся выяснить, есть ли утечки памяти в нашем программном обеспечении. Итак, я использую различные инструменты и программы, чтобы помочь мне найти возможные утечки памяти. Одним из программ, которые я использовал, был AQTime. Как и в случае с Delphi XE, это была только демонстрация. Так что я не смог получить от него никакой полезной информации. Затем я решил использовать бесплатное программное обеспечение MemProof. До сих пор он показал мне много проблем с нашим программным обеспечением, которые требуют внимания. Одним из которых является ошибка.

Как только я запускаю свою программу через MemProof, она перечисляет 2 ошибки, которые пытаются уничтожить несуществующий объект из файла модуля, system.pas. Поэтому, когда я на самом деле устанавливаю точку останова в процедуре TObject.Free, она прерывается еще до того, как моя программа запустилась полностью. Проходя процедуру Free в system.pas, я обнаружил, что TIconimage пытается уничтожить или освободить себя. Другими словами, бесплатная процедура не вызывается из моей программы до фактического запуска.

Вот актуальная бесплатная процедура:

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

После этого наблюдения я удалил точку останова и позволил программе работать полностью. Главное окно моей программы появилось, готовое для ввода пользователем. Однако я также обнаружил, что процедура TObject.Free вызывается без остановки, если какая-либо часть ОКНА моей программы отображается на экране. Я совсем этого не понимаю. Это почему? Кто-нибудь может объяснить? Как TForm связан с TObject.Free в любой форме или форме, так как процедура постоянно вызывается, когда TForm отображается на экране?

Заранее спасибо.

Ответы [ 3 ]

11 голосов
/ 17 марта 2011

Относительно того, почему TObject.Free выполняет много, каждый раз, когда объект уничтожается, любой объект, этот метод будет вызван. Все классы являются производными от TObject, это общий предок, поэтому практически любое действие в программе на Delphi включает в себя большое количество пар создания / уничтожения объектов и, следовательно, достигает TObject.Free.

Что касается обнаружения утечек памяти, у вас есть все необходимое для решения этой проблемы в Delphi. Диспетчер памяти FastMM можно запустить в режиме «отчета об утечках памяти», и он предоставит вам множество диагностических данных для любой утечки памяти.

Рассмотрим следующую тривиальную программу:

program Leaker;
begin
  ReportMemoryLeaksOnShutdown := True;
  TObject.Create;
end.

Это приводит к следующему выводу:

enter image description here

Вам просто нужно установить ReportMemoryLeaksOnShutdown на True где-то в вашем приложении (начало файла .dpr такое же хорошее место, как и любое другое).

Если вы хотите получить больше информации в отчете, вы можете загрузить полную версию FastMM и настроить ее так, как вам хочется.

Тогда вы получите такой вывод:

A memory block has been leaked. The size is: 84

This block was allocated by thread 0x1304, and the stack trace (return addresses) at the time was:
40455E [System][System.@GetMem]
405A2F [System][System.TObject.NewInstance]
40602E [System][System.@ClassCreate]
4474C2 [Classes][Classes.TStringList.Create]
C275A3 [Main.pas][Main][Main.TMainForm.CreateAuxiliaryForms][997]
C84C8A [OrcaFlex.dpr][OrcaFlex][OrcaFlex.OrcaFlex][351]
75E633CA [BaseThreadInitThunk]
77519ED2 [Unknown function at RtlInitializeExceptionChain]
77519EA5 [Unknown function at RtlInitializeExceptionChain]

The block is currently used for an object of class: TStringList

Это действительно замечательно. Это говорит мне о том, что утечка памяти была выделена в строке Main.pas 997, и именно туда я и положил свою преднамеренную утечку!

2 голосов
/ 17 марта 2011

Как вы знаете, TApplication имеет свойство Icon, которое вы можете назначить в настройках приложения в настройках проекта.Это свойство отражается в поле FIcon TApplication, которое создается в конструкторе объекта Application.TIcon имеет поле TIconImage, представляющее фактическое изображение, которое создается в его конструкторе.Когда объект Application загружается и назначает значок из файла ресурсов проекта, этот начальный «TIconImage» должен быть освобожден, чтобы предотвратить утечку.Все это происходит еще до того, как Application.Initialize вызывается в исходном коде проекта, поскольку объект Application создается из раздела инициализации 'controls.pas'.

Многое происходит, когда приложение запускается или работает,При запуске механизм потоковой передачи создает объекты (потоки ресурсов, считыватели, средства поиска классов, списки компонентов ...), а затем освобождает их.Даже пустая форма VCL (без элементов управления) при запуске создает список при каждой активации, чтобы найти элемент управления для фокусировки, а затем освобождает этот список.С помощью сложных приложений с графическим интерфейсом можно создавать и освобождать различные графические объекты, даже если навести на них указатель мыши.Или код выравнивания / расположения может создавать / освобождать объекты, даже если вы нажимаете на что-то мышью.

Для устранения утечек вы можете пройти курс, обозначенный ответом Дэвида или при использованииСторонний продукт концентрируется на том, что он говорит, утечка, а не на каждом объекте, который создается / освобождается.:)

0 голосов
/ 17 марта 2011

TObject.Free будет вызываться всякий раз, когда ЛЮБОЙ экземпляр класса в Delphi равен Свободен 'd.

Это включает в себя целый ряд созданных объектови уничтожается просто как часть обычного выполнения программы на Delphi, в том числе в ответ на события, автоматически обрабатываемые объектом TForm в ответ на сообщения, сгенерированные системой, просто для поддержания самого объекта окна в существовании в Windows собственный Диспетчер окон .

Например, рассмотрим этот фрагмент кода из TCustomForm WndProc :

      WM_MEASUREITEM:
      begin
         :
                Canvas := TControlCanvas.Create;
                with Canvas do
                try
                  :
                finally
                  Canvas.Free;
                end;
        :
      end;

Ключевым моментом здесь является то, что в ответ на сообщение WM_MEASUREITEM пользовательская форма (и, следовательно, стандартный производный класс TForm , поскольку в конечном итоге это происходит от TCustomForm ) создает временный TControlCanvas , который затем Free , когда он закончил с ним.

Это не обязательно может быть кислымCE из TObject.Free вызовов, которые вы видите в случае вашей конкретной формы, это всего лишь пример, но показывает, как просто существующий TForm может привести к other объекты создаются и уничтожаются в ответ на автоматически генерируемые системой сообщения.

...