Delphi. Повторное компиляция приложения с 10.2.1 вызывает утечку памяти?
Я только что установил Delphi 10.2 Release 1. Когда я перекомпилировал свои приложения и запускал их, у меня много утечек памяти. У меня не было утечек памяти с 10.2 (без обновления). Я также не внес изменений в код.
Чтобы проверить, я создал простое пустое приложение и поместил несколько компонентов в форму. Нет кода. Отказались от приложения и получили утечки памяти.
![Утечки памяти из примера приложения]()
Я хотел выделить это (если только предупреждение перед обновлением).
Мои вопросы:
- Кто-нибудь еще видел эту проблему?
- Есть ли что-то, что мне нужно или может сделать, чтобы избавиться от этой проблемы?
Примечание.. Я зарегистрировал проблему на портале качества, на всякий случай, это настоящая проблема: https://quality.embarcadero.com/browse/RSP-18774. В этом билете я также приложил пример приложения.
Ответы
Ответ 1
После некоторого расследования я обнаружил, что обратные вызовы, передаваемые TThread.CurrentThread.ForceQueue
в TStyledControl.KillResourceLink
, никогда не выполняются, потому что прежде чем какой-либо поток сможет обрабатывать их, приложение заканчивается, а деструктор класса TThread
уничтожает список, который все еще имеет необработанные обратные вызовы.
Я решил это, добавив вызов CheckSynchronize
в конце FMX.Forms.DoneApplication
, который заставляет выполнять обратные вызовы, которые устраняли огромную утечку памяти.
Я не знаю, правильно ли это исправление, но оно решило сообщить о утечке памяти.
Ответ 2
У меня такая же проблема с использованием С++ Builder 10.2.1 в FMX и в приложениях VCL.
Если я включу CodeGuard, я получаю утечки памяти при выходе приложения.
У меня есть TThread
с обработчиком OnTerminate
: если я поставлю точку останова в этом обработчике, когда я закрываю программу, она никогда не вызывается.
Если я помещаю CheckSynchronize()
в деструктор моей основной формы приложения, проблема остается.
Мое решение было "ужасным" циклом, подобным этому в деструкторе основной формы:
__fastcall TForm3::~TForm3(void) {
for(int i = 0; i < 10; i++) {
Sleep(1);
CheckSynchronize();
}
}
Это решение не является детерминированным, но может использоваться в вашем приложении в режиме отладки, чтобы избежать сообщений об ошибках CodeGuard.
Другое решение использует функцию WaitFor()
, если MyThread
является объектом TThread
:
MyThread = new MyThreadClass();
и DeleteThisTh()
- это метод этого класса, мы можем дождаться завершенного потока внутри DeleteThisTh()
:
void MyThreadClass::DeleteThisTh(void) {
Terminate();
WaitFor();
delete this;
}
В событии OnTerminate
я могу очистить свои объекты. Обратите внимание:
-
delete this
вызывается после OnTerminate
;
-
DeleteThisTh()
живет в основном потоке;