Средства тестирования приложений для разработчиков

       

Purfy


Исследуем поверхность и интегрируемся с VC++

Начать описание возможностей продукта Rational Purify хочется перефразированием одного очень известного изречения: "с точностью до миллиБАЙТА". И это не случайно, ведь именно на решение всех проблем, связанных с утечкой памяти и предназначен данный продукт.

Ни для кого не секрет, что многие приложения ведут себя "не слишком скромно", замыкая во время работы все системные ресурсы без большой на то необходимости. Данной болезни подвержены в основном крупные программные пакеты, и возникает подобная ситуация по причине нежелания программистов доводить созданный код "до ума", но чаще подобное происходит не из за лени, а из-за невнимательности. Это понятно - современные темпы разработки ПО в условиях жесточайшего прессинга со стороны конкурентов не позволяют уделять слишком много времени оптимизации кода, ведь для этого необходимы и высокая квалификация, и наличие достаточного количества проектного времени. Как правило квалификация есть, а вот времени и денег на детальное тестирование кода на наличие "глюков" и "багов" практически нет. И в большинстве случаев, идя на поводу у клиентов крупные компании выпускают сырой код и тут же принимаются "латать" его различными патчами:

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

Так вот, как мне видится, имея в своем распоряжении надежный инструмент, который бы сам в процессе работы над проектом указывал бы на подобные ошибки, то разработчики начали бы его повсеместное внедрение, повысив надежность создаваемого ПО, поскольку, как известно, что проще ошибку не допустить, чем потом с гордостью исправлять.

В общих чертах работа Rational Purify сводится к детальному выводу статистики об использовании памяти приложением (список ошибок и примеры устранения во второй главке).

Получаемой статистики вполне достаточно для получения общей, а затем - и детальной информации обо всем, что имеет отношение к памяти: утечки, потерянные блоки, фиктивные ссылки.

Purify позволяет анализировать исполняемый модуль, содержащий отладочную информацию, либо работать на уровне исходников, но только в среде Visual Studio (C++, Basic, Java).

Работа программы начинается со сбора информации о загружаемых библиотеках.
То есть программа отыскивает ошибки не только внутренние но и внешние, разумеется, нельзя исправить ошибку в системной DLL, но если она там есть, то наверняка, можно написать дополнительный код в своей процедуре, отказавшись от вызова "некачественной" функции из DLL. Перво-наперво идет детальное инструментирование всех модулей. Инструментирование сводится к тому, что Purify вставляет свою отладочную информацию в тело программы и вызываемых библиотек (технология Object Code Insertion). Для эффективной работы все "пройденные" библиотеки хранятся в кеше, что позволяет сократить необходимое время не перезапуск исправленного приложения. Давайте рассмотрим возможности Purify в плане совместной работы с Microsoft Visual C++. Интеграция компонентов от Rational выражается в появлении новых инструментальных панелей на поверхности рабочего стола в Development Studio. Получив полный набор тестирующих и профилирующих средств, разработчик обращается к ним по мере необходимости, не покидая рабочего пространства, что позволяет сэкономить массу времени на различные вызовы сторонних программ. Рисунок 1 показывает примерный вид инструментальных панелей в Visual Studio, появляющихся после инсталляции Purify, Quantify, PureCoverage. (вставить сюда из файла INTEGRATION.tif) А учитывая давнюю дружбу Rational и Microsoft, становится понятно, почему поддерживаются в полной мере только среды разработчиков от MS. Собрав воедино всю перечисленную информацию, давайте попробуем на конкретном примере в Visual C++, создать приложение, внести в него ряд намеренных ошибок после чего, используя Purify попытаться отыскать их. Опустим за скобки то, каким образом создаются проекты в Visual Studio и из чего они состоят - это не самоцель. Исходим из того, что читатель уже работал с данной средой, или хотя бы знаком с ней - это - во-первых. Во-вторых, для чистоты эксперимента мы воспользуемся стандартным "Волшебником" из состава Visual Studio, сгенерировав, на его основе проект, в который внесем некоторый код, который будет неадекватно себя вести с памятью системы: Итак, у меня получилось 32-разрядное приложение для Windows с именем "PROJECTOID".


На рисунке 2 изображен скриншот окна Workspace после создания проекта. Для демонстрации преимуществ Purify не нужно заводить в примере тонны сложных классов, запутывая и себя, и программу, и статью: ограничимся лишь простыми вызовами на распределение памяти.

Для более наглядного способа отлова ошибок допишем пару строк в стандартный обработчик "OnAppAbout": void All::OnAppAbout() { char *alex; //Наша строка №1 alex=(char *)malloc(20000); //Наша строка №2 CAboutDlg aboutDlg; aboutDlg.DoModal(); } Добавление интеллекта к функции OnAppAbout сделано намерено, поскольку во время работы можно воспользоваться данной функцией несколько раз подряд, активируя диалог "ABOUT" после игр с его вызовом. Теперь завершим приложение, посмотрим статистику по памяти и под конец найдем "виновного" в полученной утечке памяти. Из фрагмента видно, что указатель "alex" смотрит в сторону блока длиной в 20Кб, который выделяется функцией MALLOC. Еще можно заметить, что: 1) указатель нигде не используется, 2) Блок памяти не освобождается. Запускаем программу по F5, предварительно активировав Purify (увеличительные стекла на инструментальной панели Purify. См. рис. 1). В запущенном приложении трижды запускаем диалог ABOUT из верхнего меню и закрываем приложение. Во время работы подконтрольного приложения Purify собрала достаточно информации о нем и о его проблемах с памятью. Полученная статистика выведется на экран сразу по окончании работы приложения. Рисунок 3 иллюстрирует вид окна со статистикой по памяти. При внимательном рассмотрении становится видна вся подноготная как нашего модуля, так и шапки, сгенерированной компилятором Microsoft в лице Visual C++. Purify насчитала 43 (!) предупреждения о неправильном (читай: неэффективном) использовании памяти, а из них только одно наше было преднамеренно введено в программу. Хотя, если говорить совсем честно и открыто, то не все ошибки являются ошибками! (см вторую главку)
Вновь обратимся к рисунку со статистикой, где в явном виде находится информация по ошибкам и по модулям, в которых эти ошибки были обнаружены.


К приятной неожиданности можно отнести фразу "Memory leak of 60000", указывающую на то, сколько фактических байтов памяти программа не вернула системе, по завершении своей работы. Эта черта разительно отличает подходы к тестированию программы Rational Purify от подобных продуктов конкурирующих компаний, которые высчитывают не фактические утечки (полученные в результате нескольких вызовов при реальной работе приложения, а количество невозвращенных блоков, то есть ограничиваются лишь анализом (на уровне исходных текстов) программы с выявлением вызовов функций аллокирования памяти без последующего освобождения. Из этого и следует полученное число 60000 - фактически не освобожденных блоков (3 по 20000). После добавления функции free(alex) в конец обработчика OnAppAbout и перекомпиляции тестируемого приложения, Purify не обнаруживает никаких ошибок памяти, что и являлось нашей целью. Рисунок 4 отображает окно c ошибкой, в котором Purify, подсветила конкретный фрагмент текста листинга.
Все вышеописанные возможности дают мощный инструментарий в руки разработчика, желающего знать, где в коде находится вызов на выделение памяти, и сколько физически утеряно блоков в результате работы приложения, и какая часть программы в этом виновата. Продукт поставляется в Россию компанией Interface Ltd.:

Содержание раздела