Отладка приложений

       

Куда направляются отчеты об утечках памяти?


Решив проблему инициализации, удалось, наконец, получить работающее расширение MemDumperValidator. И все работало хорошо — за исключением того, что функции, выдающие дампы при обнаружении утечек памяти, по завершении программы не генерировали удобно отформатированного вывода. Дампы памяти оказывались стандартными дампами DCRT-биб-лиотеки. Прослеживание "потерявшихся" отчетов об утечках показало, что функции завершения DCRT-библиотеки вызывают функцию _crtsetDumpclient с параметром NULL (пустой указатель), очищая, таким образом, подключение дампа перед вызовом функции _crtDumpMemoryLeaks. Стало понятно, что нужно просто самому выполнить заключительную проверку утечки памяти. К счастью, у меня нашлось подходящее место, чтобы выполнить эту операцию.

Общий Вопрос Отладки

Зачем нужна отладочная DCRT-библиотека, если используется инструмент обнаружения ошибок типа утилиты BoundsChecker?

Инструменты обнаружения ошибок, такие как BoundsChecker от Compuware NuMega и Purify от Rational Software автоматически обрабатывают записи, перезаписи (underwrites и overwrites) и утечки памяти. Если вы используете один из этих инструментов, то, вероятно, думаете, что на DCRT-библиотеку не стоит тратить время и усилия. Технически это так, но, чтобы гарантированно разрешить все проблемы с памятью, необходимо запускать приложение под управлением инструмента обнаружения ошибок каждый раз, когда кто-то из команды разработчиков выполняет отладочное построение (debug build) приложения. Таким партнером по отладке может быть кто угодно — вы сами, ваши коллеги разработчики и, если вы следовали рекомендациям из главы 2, то даже сотрудники отдела контроля качества.

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

Поскольку директива #pragma init_seg(compiler) уже использовалась для предварительной инициализации класса AutoMatic (и вызова деструктора после выполнения самого последнего оператора приложения), то в этой же точке исходного кода нужно было выполнять и проверку утечки памяти, а затем выключать флажок _CRTDBG_LEAK_CHECK_DF, чтобы DCRT-библиотека не выводила собственных отчетов. Единственное предостережение — при использовании этого подхода необходимо удостовериться, что выбранная CRT-библиотека включается перед файлом BUGSLAYERUTIL.LIB (если компоновка выполняется с ключом /NODEFAULTLIB). При компоновке файла BUGSLAYERUTIL.LIB может оказаться, что CRT-библиотеки не зависят от соответствующих директив #pragma init_seg(compiler), гарантирующих, что данные этих библиотек инициализируются первыми, а разрушаются последними, так что поддерживать правильный порядок в размещении этих директив программист должен самостоятельно.

Здесь речь идет о размещении указанной директивы перед исходным кодом отлаживаемого приложения. — Пер.

Если внимательно подумать, то установка режима чистки обработчиков функций вывода дампов DCRT-библиотекой имеет определенный смысл. Если бы ваш обработчик использовал какую-нибудь функцию из CRT-библиотеки (скажем, printf), то он мог бы завершить вашу программу аварийно, потому что, когда вызывается функция _crtDumpMemoryLeaks, CRT-библиотека находится где-то в середине процесса завершения своей работы. Надо соблюдать правила и всегда компоновать DCRT-библиотеку перед компоновкой любых других библиотек, т. к. функции расширения MemDumperValidator завершаются прежде, чем заканчивает работу DCRT-библиотека. Чтобы обойти подобные проблемы, применяйте в дамп-функциях только макросы _RPTn и _RPTFH, потому что их использует и функция _CrtDumpMemoryLeaks.



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