Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
17 матлаб.docx
Скачиваний:
2
Добавлен:
01.03.2025
Размер:
93.6 Кб
Скачать

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

Как работает отладчик

В отладке принимают участие два процесса – отладчик (debugger) и отлаживаемый (debuggee). Отладчик имеет полный контроль над отлаживаемым процессом. Он может приостанавливать и возобновлять его потоки, читать или изменять память и регистры процессора и т. д. Кроме того, отладчик получает уведомления обо всех важных событиях, которые происходят в отлаживаемом процессе. К таким событиям относятся запуск или завершение новых процессов и потоков, загрузка и выгрузка DLL, исключения, а также вывод отладочной информации посредством функции OutputDebugString. В случае возникновения одного из этих событий отлаживаемый процесс приостанавливается и ждёт, пока отладчик не выполнит необходимые действия и возобновит его работу. Завершение отладчика приводит к завершению отлаживаемого процесса.

Точки останова

Точки останова (breakpoints) играют важную роль в отладке приложений. На самом деле, точка останова – это некоторое условие (например, достижение определённой команды в программе), при выполнении которого возбуждается исключение EXCEPTION_BREAKPOINT (0x80000003). Как мы уже знаем, исключение приводит к тому, что отлаживаемый процесс приостанавливается, а отладчик получает управление. В частности, он может считать текущие значения регистров процессора и ячеек памяти и выдать их на экран для анализа. После этого он может возобновить выполнение отлаживаемого процесса по команде программиста.

Для реализации точек останова в Visual C++ используется специальная инструкция процессора (int 3 на процессорах Intel). Выполнение этой инструкции приводит к исключению EXCEPTION_BREAKPOINT. Установить точку останова можно в любом месте программы. Для этого отладчик записывает по соответствующему адресу инструкцию int 3 (1 байт с кодом 0xCC). Очевидно, что это можно сделать и вручную, вставив в программу инструкцию __asm int 3. Можно также использовать функцию DebugBreak из Win32 API. Ниже мы увидим, для чего применяется этот приём.

В современных процессорах Intel существуют отладочные регистры (DR0-DR7), которые позволяют установить до 4 аппаратных точек останова. Visual C++ использует эти регистры, но когда их количества оказывается недостаточно, их функциональность эмулируется посредством int 3.

С помощью точек останова в отладчике Visual C++ реализовано множество полезных возможностей, например, пошаговая отладка (режим, в котором пользователь может выполнять по одной инструкции отлаживаемой программы за раз).

Отладочные символы

Конечно, возможность читать данные из памяти отлаживаемого процесса полезна. Но для программиста на C++ гораздо удобнее просматривать значения переменных, а не безликих ячеек памяти. Пошаговую отладку также гораздо удобнее выполнять по исходному тексту программы, а не по ассемблерному листингу. Чтобы это стало возможным, применяются отладочные символы (debugging symbols). Эти символы генерируются в процессе построения программы. Существуют различные форматы записи символов. По умолчанию Visual C++ записывает их в отдельный файл с расширением PDB, включая в приложение или DLL абсолютный путь к этому файлу.

PDB-файл содержит информацию, которая позволяет определить адрес любой переменной, функции или строки кода. Возможно и обратное преобразование. Кроме того, в PDB-файл включается информация о типах. Благодаря этому отладчик может не только считать из памяти значение переменной, но и выдать это значение на экран в определённом виде (в зависимости от типа переменной). Пошаговая отладка по исходному тексту также становится возможна (при условии, что у вас есть этот исходный текст, так как он не включается в PDB-файл).

Обратите внимание, что отладочные символы хранятся отдельно для каждого модуля (EXE или DLL). Вполне возможна ситуация, когда отладочные символы доступны для DLL, которую загружает приложение, но не для самого приложения. В этом случае код DLL можно будет отлаживать на уровне исходных текстов, а код приложения – на уровне ассемблера.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]