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

Модификаторы позиционных точек прерывания


Мы рассмотрели вопросы правильного размещения экспортируемых функций, и теперь читатель должен уверенно устанавливать позиционную (location) точку прерывания в любом месте приложения. Роль позиционных точек прерывания в отладочном процессе довольно значительна, но, как было указано в начале данной главы, к ним можно также добавить некоторый "интеллект" с целью повышения эффективности работы отладчика. Носителями этих "интеллектуальных" возможностей являются специальные модификаторы позиционных точек прерывания: счетчики пропусков, условные выражения и изменения переменных.

Счетчики пропусков

Самый простой модификатор позиционной точки прерывания (Tll) — это счетчик пропусков (skip count). Он указывает отладчику, что нужно вставить точку прерывания, но пропускать ее выполнение (т. е. не приостанавливать приложение в этой точке) указанное количество раз. С помощью этого модификатора легко решается проблема прерывания на нужной итерации цикла.

Добавлять счетчик пропусков к простой точке прерывания довольно легко. Сначала установите обычную позиционную точку прерывания и раскройте диалоговое окно Breakpoints. Выделите позиционную точку прерывания в списке Breakpoints, и щелкните кнопку Condition. Затем в нижнем редактируемом поле диалогового окна Breakpoint Condition введите нужное число пропусков точки прерывания.

Когда отладчик, наконец, остановит выполнение приложения в такой точке, он сообщит, сколько раз выполнялся помеченный им оператор. Если есть цикл, в котором имеет место аварийный останов, но неизвестно, на какой итерации это происходит, то нужно добавить позиционную точку прерывания со счетчиком пропусков к строке какого-нибудь оператора внутри цикла. Значение счетчика пропусков должно быть больше, чем общее число итераций цикла. Когда программа завершится аварийно, откройте диалоговое окно Breakpoints и посмотрите на точку прерывания, обозначенную в списке Breakpoints1. После строки описателя точки прерывания располагается остаток счетчика пропусков (в круглых скобках).



Знание различных псевдорегистров, которые обеспечивают доступ к регистровым и специальным значениям, а также творческий подход — вот два секрета применения условных выражений. Например, хотя отладчик Visual C++ не имеет явного метода для установки позиционной точки прерывания, которая срабатывает только в определенном потоке под Windows 2000, но если установить выражение @TIВ=линейный адрес TIB, то прерывание произойдет только на указанном потоке. Первый шаг заключается в том, чтобы ввести псевдорегистр @ТIB в окно Watch и найти линейный адрес информационного блока потока, на котором требуется выполнить прерывание. Чтобы активизировать поток, который надо проверить, можно использовать диалоговое окно Threads отладчика. Если, например, поток содержит в псевдорегистре @Т1В адрес, равный Ox7FFDEOOO, то выражение выглядит так: @TIB == Ox7FFDEOOO. Для Windows 98 нужно просмотреть регистр FS, который является уникальным для каждого потока, и задать выражение @FS == значение конкретного потока (thread specific value).

Для того чтобы выполнить прерывание, основанное на конкретном коде последней ошибки (last error code), можно использовать псевдорегистр @ERR. Например, чтобы выполнить прерывание после API-вызова, который, согласно документации Platform SDK, может сгенерировать последнюю ошибку ERROR_FILE_NOT_FOUND, выражение должно выглядеть так: @ERR==2. Числовое значение ошибки с идентификатором ERROR_FILE_NOT_FOUND можно найти в файле WINERROR.H. Все псевдорегистры перечислены в табл. 5.1.

Наконец, из-за того что нельзя вызывать функции в таких выражениях, прерывание на строке с конкретным (строчным) значением затруднительно.

 TIB — Thread Information Block, информационный блок потока. — Пер.

В этом случае просто установите выражение, которое проверяет каждый символ, например, так:

(szBuff[0] = 'Р')-&& (szBuff [l] = 'a'j&& (SzBuff [2] == 'm').

Другой способ использования условных выражений в прерываниях: можно комбинировать их со счетчиком пропусков.


Такой прием позволяет выполнить прерывание, когда n-ое значение выражения станет равно true (где п — исходное значение счетчика пропусков).

Таблица 5.1. Выражения и псевдорегистры окна Watch

Псевдорегистр

Описание

©ERR

Значение последней ошибки; то же значение возвращается API-функцией GetLastError

©TIB

Информационный блок текущего потока; необходим, потому что отладчик не обрабатывает формат FS:0

©CLK

Недокументированный регистр часов; используется только в окне Watch

@ЕАХ, @ЕВХ, ©ЁСХ, @EDX, ©ESI, ©EDI, ©EIP, ©ESP, ©EBP, ©EFL

Регистры Intel CPU

@CS, @DS, @ES, @SS, @FS, ©GS

Сегментные регистры Intel CPU

©STO, ©ST1, @ST2, ©ST3, ©ST4, ©ST5, ©ST6, ©ST7

Регистры чисел с плавающей точкой Intel CPU

Изменения переменных

Последний модификатор позиционных ТП связан с изменением значения переменной. Позиционная ТП с этим типом модификатора останавливает отладчик, когда изменяется значение указанной в ней переменной. Следует помнить, что переменная проверяется только тогда, когда позиционная точка прерывания срабатывает (т. е. когда отладчик останавливает выполнение приложения). Этот модификатор применяется, например, если известно, что в функции более высокого уровня происходит перезапись памяти, и необходимо свести к минимуму ущерб, который может при этом принести вызов функции более низкого уровня. В такой ситуации установите позиционные точки прерывания после каждого вызова функции и выполните в них проверку изменения значения переменной. Преимуществом данной методики является возможность просмотра отладчиком целого буфера, если это необходимо.

Добавление этого модификатора происходит точно так же, как добавление других модификаторов позиционных точек прерывания — с использованием диалогового окна Breakpoint Condition для установки необходимых условных параметров. Единственное недоразумение может возникнуть из-за того, что редактируемое поле (Enter the expression to be evaluated), в которое вводится наблюдаемая переменная, является одновременно и полем для ввода условного выражения.


В среднем редактируемом поле диалогового окна Breakpoint Condition (с именем Enter the number of elements to watch in an array or structure) пользователь сообщает отладчику, сколько элементов массива или области памяти надо наблюдать. Если значение, на котором требуется выполнить прерывание, является разыменованием указателя, например, *pMyData, то в это поле нужно ввести число наблюдаемых байт.

 Чтобы открыть эту панель, нужно установить на подходящем исходном операторе простую позиционную точку прерывания и, не изменяя позиции курсора ввода, ввести команду Edit|Breakpoints, Затем в открывшемся диалоговом окне Breakpoints ввести в поле Break at вкладки Location номер строки (после символа "точка"), в которой установлена данная точка прерывания (например, .47), и нажать кнопку Condition (под полем Break at). — Пер.

 Если же ввести в поле Enter the expression to be evaluated сам указатель pMyData (без звездочки), то прерывание произойдет, когда изменится сам указатель, указывающий на другую область памяти. — Пер.



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