Deleaker…

Одной из распространенных проблем, с которыми сталкиваются программисты, являются утечки памяти или утечки ресурсов другого типа. Например, Windows ограничивает количество объектов GDI или USER32, которые процесс может выделить одновременно. Программисты, которые пишут на Delphi, не являются исключением.

Некоторые современные IDE имеют встроенные возможности обнаружения утечек (увы, только памяти). Недавно в Visual Studio появился инструмент для отображения списка указателей на память, выделенной из кучи. К сожалению, утечка может быть вызвана не только выделением памяти из кучи, но полученной вызовом функций COM (вроде CoTaskMemAlloc), виртуальной памяти, отображением файлов в память и многих других. К сожалению, утечки дескрипторов, а также GDI ресурсов вовсе не обнаруживаются той же Visual Studio (кстати, Deleaker обнаруживает все виды утечек и может работать и в Visual Studio).

RAD Studio совсем не имеет встроенных инструментов такого рода. Но представьте, как было бы замечательно, если бы при отладке разработчик мог просто нажать на заветную кнопку и посмотреть, где и в каком месте в коде была выделена память, открыты файловые и другие дескрипторы, объекты GDI!

Недавно было выпущено такое расширение, Deleaker, которое может делать все это и многое другое. Первоначально Deleaker был создан как расширение для Visual Studio, но в вскоре он стал поддерживать и другие IDE, включая RAD Studio и Qt Creator.

Загрузить пробную версию можно тут: https://www.deleaker.com/download.html

Посмотрим, как пройдет установка. Инсталлятор предлагает добавить Deleaker к версиям RAD Studio, установленным на компьютере:

Ну а как Deleaker покажет себя в деле?

Для теста давайте создадим простое приложение Windows VCL и добавим утечку в FormCreate:

procedure TForm1.FormCreate(Sender: TObject);
var
  StringList: TStringList;
begin
  StringList := TStringList.Create;
end;

Собираем и запускаем отладку. Переключаемся обратно в RAD Studio и нажимаем DeleakerDeleaker Window. В появившемся окне кликаем на Take Snapshot, чтобы получить снапшот – список всех текущих аллокаций. Среди них есть наш объект TStringList. Вы можете изучить стек, который был сохранен в момент создания этого объекта:

Если вы переключитесь на вкладку Delphi Objects, то там вы увидите список объектов, сгруппированных по классам:

Закройте окно приложения, чтобы завершить отлаживаемый процесс. Как только процесс завершился, Deleaker создает снапшот, который необходим для того, чтобы выяснить, какая память, какие объекты и другие ресурсы не были освобождены (что, собственно, и называется утечками), а, главное, где именно:

Еще одна полезная функция – сравнение двух снапшотов. Например, разработчик понимает, что процесс постоянно потребляет память и не возвращает ее, или число объектов GDI увеличивается и увеличивается. Можно просто получить снапшот и изучить его, но гораздо удобнее получить первый (базовый) снимок, а затем дать процессу некоторое время для выделения новых ресурсов. Далее сделать новый снапшот и сравнить его с базовым.

Чтобы понять, как это работает на практике, добавим таймер, и каждые полсекунды пусть он будет создавать новый объект, а также открывать файл:

procedure TForm1.Timer1Timer(Sender: TObject);
var
  StringList: TStringList;
begin
  StringList := TStringList.Create;
  CreateFile('1.tmp', GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_DELETE, nil, CREATE_ALWAYS, 0, 0);
  DeleteFile('1.tmp');
end;

Запускаем отладку, переключаемся в Deleaker. Можно понаблюдать, как ресурсы выделяются процессом на специальном графике:

Давайте сделаем два снапшота, потом выберем первый и нажмем “Compare with…“, чтобы увидеть разницу между ними, а именно мы получим те ресурсы, которые были выделены с момента создания первого снимка:

Таким образом, разница между последовательными снапшотами позволяет увидеть новые аллокации, и большое значение имеет столбик “Hit Count“, в котором показывается сколько раз ресурс был выделен в одном и том же месте кода.

Deleaker – полезное расширение для исследования памяти и других ресурсов, а также для обнаружения утечек. Вы можете посмотреть информацию о конкретном блоке памяти или дескриптора, для каждого такого объекта доступен стек вызовов, поэтому легко найти место, в котором был произведено выделение ресурсов.

Для тех, кто хочет посмотреть вживую, как работает Deleaker в Delphi, вот ролик с демонстрацией:


You may also like...