Точки прерывания Windows-сообщений
Точки прерывания Windows-сообщений (Windows message breakpoints) останавливают отладочный прогон приложения, когда оконная процедура этого приложения получает определенное Windows-сообщение. Точки прерывания этого типа устанавливаются на вкладке Messages диалогового окна Breakpoints (рис. 5.5). Для программ, разработанных средствами SDK1 языка С, установка этой точки прерывания достаточно проста, потому что когда выполняется подчиненный отладчик, раскрывающийся список поля Break at WndProc уже содержит имя нужной оконной процедуры. Для установки таких ТП нужно:
1. Выбрать из списка Break at WndProc оконную процедуру.
2. Выбрать из списка Set one breakpoint for each message to watch идентификатор того сообщения, при получении которого должно произойти прерывание.
3. Нажать кнопку ОК.
Если в списке Set one breakpoint for each message to watch нет подходящего идентификатора, его следует ввести в это поле вручную.
В настоящее время в Windows-программировании широко используются библиотеки С++-классов, такие как MFC, позволяющие напрямую работать с точками прерывания Windows-сообщений. Если установить ТП этого типа на главной оконной процедуре MFC: {, ,MFC42D.DLL}AfxWndProc, то она будет работать. Однако такая установка позволяет останавливать приложение только на сообщениях главного окна приложения. Если нужно выполнять прерывания на частных Windows-сообщениях, обрабатываемых в оконных процедурах дочерних оконных классов (производных от класса cwnd), то придется перенести эту ТП из AfxWndProc на оконную процедуру дочернего окна.
1 SDK (Software Development Kit) — инструментальная система разработки программ. — Пер.
Если нужно выполнить прерывание на общем сообщении, то лучше использовать условную позиционную точку прерывания, устанавливая ее в MFC-методе cwnd: :WindowProc. Для этого сначала нужно найти значение this-ука-зателя интересующего вас класса, а затем отыскать в файле WINUSER.H значение Windows-сообщения, на котором требуется остановить программу. С помощью этих двух значений нужно установить позиционную точку прерывания в cwnd: :WindowProc.
При написании данного раздела автор отлаживал программы пакета Visual C++ 6.0 Service Pack 3, и чтобы выполнять прерывание на сообщении WM_PAINT только от своего класса, он установил расширенную позиционную точку прерывания со следующим описателем:
{,WINCORE.CPP,}.1584 when (this=Ox0012FE74)&&(message==OxF)
При использовании точки прерывания с выражением "this. ..&&.. .message" нужно проявлять осторожность, потому что указатель this, вероятно, изменяется в зависимости от способа выделения памяти вашему классу и от изменений, вносимых в отлаживаемый код. Если же необходимо быстро установить точку прерывания, то всегда можно добавить метод обработки (с помощью мастера классов Class Wizard) и установить на нем простую (не расширенную) позиционную точку прерывания.
В этой главе много внимания уделено расширенным точкам прерывания. В листинге программы AdvancedBP показаны все типы точек прерывания, кроме прерываний от Windows-сообщений. Синтаксис точек прерывания каждого типа показан в виде строчных комментариев в исходном коде программы (что позволяет видеть соответствующие описатели без открытия диалогового окна Breakpoints). Настоятельно советую всем разработчикам попрактиковаться в установке расширенных точек прерывания в собственных программах. Поразительно, как много полезного можно узнать при этом и об отладчике, и о собственном проекте!
Общий вопрос отладки
Почему точки прерывания исчезают или перескакивают с места на место?
Содержать в порядке точки прерывания исходного кода помогает редактор интегрированной среды разработки (IDE) Visual C++, потому что именно он удерживает точки прерывания на соответствующей строке кода. Если приходится редактировать исходный код вне IDE, и точка прерывания оказывается установленной не на активной строке исходного кода, то отладчик отреагирует на это следующим сообщением:
One or more breakpoints are not positioned on valid lines.
These breakpoints have been moved to the next valid line.
(Одна или несколько точек прерывания не были позиционированы на правильной строке. Эти точки прерывания перемещены к следующей правильной строке).
Отладчик всегда перемещает точки прерывания вниз по тексту, так что если удалить какую-нибудь строку кода, то, чтобы гарантировать их появление на надлежащих строках, нужно выполнить на них двойной щелчок (левой кнопкой мыши).
Если отладчик вообще не может установить точку прерывания, вы получите сообщение:
One or more breakpoints cannot be set and have been disabled. Execution will stop at the beginning of the program.
(Одна или несколько точек прерывания не могут быть установлены и были отключены. Выполнение остановится в начале программы.)
Нажав кнопку ОК, чтобы закрыть панель сообщения, нужно открыть диалоговое окно Breakpoints и отыскать точки прерывания со сброшенными флажками. Они-то и доставили неприятности отладчику.
Наиболее общей причиной отказа в установке точек прерывания является попытка установить точку прерывания в явно загруженную DLL — т. е. в DLL, загруженную явным обращением к API-функции LoadLibrary. Все DLL-файлы модели компонентных объектов (СОМ) загружаются явно, так что эта проблема возникает с раздражающей частотой. Отладчик должен установить все точки прерывания еще при запуске, поэтому в начале отладки нужно будет вручную добавить к списку дополнительных DLL явно загруженные DLL (чтобы заставить отладчик загрузить символы этих DLL). В диалоговом окне Project Settings на вкладке Debug выберите пункт Additional DLLs в списке Category. В списке Modules добавьте все DLL, которые проект может когда-либо загружать.
Кроме того, установка опций оптимизации для компилятора может передвинуть или отключить точки останова. Выбирая тип оптимизации, знайте, что компилятор может перемещать код таким образом, что отладчик не сможет установить позицию точки прерывания.
Эту панель можно открыть командой Project|Settings из Microsoft Visual C++.— Пер.