Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Роббинс Д. - Отладка приложений для Microsoft .NET и Microsoft Windows - 2004

.pdf
Скачиваний:
353
Добавлен:
13.08.2013
Размер:
3.3 Mб
Скачать

ГЛАВА 4 Поддержка отладки ОС и как работают отладчики Win32

151

 

 

Dr. Watson, но, когда я подошел к Visual Studio .NET (на самом деле к VS7JIT.EXE, который в свою очередь вызывает отладчик Visual Studio .NET), стало выскакивать сообщение, что JIT отладка заблокирована и отладку запустить невозможно.

Рис. 4 2. Диалоговое окно выбора отладчика программы DBGCHOOSER

Во первых, я был в некотором замешательстве от того, что происходит, но с помощью прекрасной программы мониторинга реестра Regmon от Марка Русси новича и Брайса Когсвелла с www.sysinternals.com я увидел, что VS7JIT.EXE прове рял значение Debugger раздела реестра AeDebug, установлен ли он как оперативный отладчик. Если нет, выскакивало сообщение о том, что оперативная отладка за блокирована. У меня была возможность проверить, что это так, остановив DBGC HOOSER в отладчике, когда он был активизирован благодаря аварийному завер шению, и изменив значение раздела реестра Debugger так, чтобы он указывал на VS7JIT.EXE. Я не понимал, почему VS7JIT.EXE считает это столь важным, что он не может заниматься отладкой, если он не является оперативным отладчиком. Я быстренько написал в DBGCHOOSER, как обмануть VS7JIT.EXE путем подмены значения Debugger на VS7JIT.EXE перед его порождением, и все в этом мире стало прекрасно. Чтобы сделать DBGCHOOSER.EXE вновь оперативным отладчиком, я создал поток, который ждет 5 секунд и восстанавливает значение Debugger.

Как я упоминал, когда завел речь о DBGCHOOSER, мое решение несовершен но из за проблем в оперативном отладчике Visual Studio .NET. В Windows XP я проверял различные варианты запуска и работы Visual Studio .NET, но нашел, что VS7JIT.EXE прекращает свою работу. Поиграв с ним немного, я понял, что в дей ствительности исполняются два экземпляра VS7JIT.EXE, в то время как Visual Studio

.NET запускается как оперативный отладчик. Один экземпляр порождает Visual Studio .NET IDE (среду интерактивной разработки), а другой работает под DCOM сервером RPCSS. В редких случаях, только при тестировании готовой реализации, я приводил систему в состояние, когда попытка породить VS7JIT.EXE была безус пешной, так как не мог запуститься экземпляр DCOM. В основном я сталкивался с этой проблемой, работая над кодом восстановления значения Debugger раздела реестра AeDebug. Идя по такому пути реализации DBGCHOOSER, я столкнулся с этой проблемой пару раз, и только когда тестировал различные случаи одновремен ного аварийного завершения нескольких процессов. Я не смог вычислить точную причину и никогда не видел этого при нормальной работе.

152 ЧАСТЬ II Производительная отладка

Автоматический запуск отладчика (опции исполнения загружаемого модуля)

Трудней всего отлаживать приложения, запускаемые другими процессами. В эту категорию попадают службы Windows и внепроцессные COM серверы. Зачастую можно вызвать API функцию DebugBreak, чтобы заставить отладчик присоединиться к вашему процессу. Однако DebugBreak не работает с двумя экземплярами. Во пер вых, иногда она не работает со службами Windows. Если вам надо отлаживать процедуру запуска службы, то вызов DebugBreak позволит отладчику присоединиться, но время, затраченное отладчиком на свой запуск, может превысить тайм аут за пуска службы, и Windows ее остановит. Во вторых, DebugBreak не работает, если вам нужно отлаживать внепроцессный COM сервер. При вызове DebugBreak обра ботчик ошибок COM обнаружит исключение, возникающее в точке прерывания и прекратит выполнение внешнего COM сервера. К счастью, Windows позволяет указать, что приложение должно запускаться в отладчике. Это позволяет запустить отладчик прямо с первого оператора. Прежде чем разрешить эту возможность, убедитесь, что при конфигурировании своей службы вы разрешили ей взаимодей ствовать с рабочим столом.

Для настройки автоматической отладки лучше всего указать эту опцию в ре дакторе реестра. В разделе HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\Current Version\Image File Execution Options создайте свой раздел, имя которого совпадает с именем файла вашего приложения. Так, если ваше приложение называется FOO.EXE, создайте раздел реестра FOO.EXE. В разделе реестра вашего приложения создайте новое строковое значение Debugger и введите в нем полный путь и имя файла выбранного вами отладчика.

Теперь, когда вы запускаете свое приложение, отладчик запускается автомати чески при загрузке приложения. Если надо указать отладчику какие либо параметры командной строки, укажите их также в значении Debugger. Например, если вы хо тите задействовать WinDBG и автоматически инициировать отладку сразу после запуска WinDBG, заполните Debugger строкой d:\windbg\windbg.exe g.

Для использования Visual Studio .NET в качестве предпочтительного отладчи ка придется сделать немного больше. Первая проблема в том, что Visual Studio .NET не может отлаживать исполняемый модуль без файла решения. Если вы разраба тываете исполняемый модуль (иначе говоря, вы располагаете решением и исход ным кодом), можете применить это решение. Однако последняя открытая ком поновка и будет запускаться. Значит, если вам надо отлаживать поставляемую компоновку (release build) или двоичный образ, для которого у вас нет исходно го кода, откройте проект, настройте активное решение как Release и закройте решение. Если вы не располагаете файлом решения для исполняемого файла, в меню File выберите пункт Open Solution и откройте исполняемый образ как ре шение. Запустите отладку и, когда появится запрос сохранения файла решения, сохраните его.

Имея решение, вы сможете им пользоваться, а командная строка, указываемая в параметре Debugger, будет выглядеть следующим образом. Если вы не добавили вручную каталог Visual Studio .NET <Каталог установки VS.NET >\ Common7\IDE к системной переменной среды PATH, укажите полный путь и каталог для DEVENV.EXE.

ГЛАВА 4 Поддержка отладки ОС и как работают отладчики Win32

153

 

 

Ключ /run командной строки DEVENV.EXE заставляет его начать отладку решения, указанного в командной строке.

g:\vsnet\common7\ide\devenv /run d:\disk\output\wdbg.sln

Вторая проблема, с которой вы встретитесь, в том, что строковый параметр Debugger может быть не более 65 символов в длину. Если вы установили Visual Studio

.NET по умолчанию, то почти наверняка путь будет очень длинным. Все, что вам нужно сделать, — это поработать с командой SUBST и назначить пути к DEVENV.EXE и вашему решению буквам устройств.

Ветераны могут помнить, что параметр Debugger легко установить с помощью GFLAGS.EXE — небольшой утилиты, поставляемой вместе с WinDBG. Увы, GFLAGS.EXE работает неправильно и принимает командную строку длиной толь ко до 25 символов для параметра Debugger. В итоге проще всего создать раздел реестра для процесса и параметр Debugger вручную.

Стандартный вопрос отладки

Мой шеф посылает мне так много почты, что я не могу ничего делать. Есть ли какой-нибудь способ замедлить эту жуткую почту от ШСИ?

Хотя многие начальники «стараются сделать как лучше», их непрекращаю щиеся сообщения по электронной почте могут отвлекать вас и не давать вам работать. К счастью, есть простое решение, которое очень хорошо ра ботает и даст вам около недели замечательного спокойствия, в результате вы сможете работать, укладываясь в сроки. Чем менее технически опытны шеф и администраторы сети, тем больше времени вы получите.

В предыдущем разделе я говорил о разделе реестра Image File Execution Options и о том, что, когда вы настроите параметр Debugger вашего процес са, процесс будет автоматически запускаться под отладчиком. Вот как из бавиться от почты ШСИ (шефа, сидящего как на иголках).

1.Зайдите в кабинет шефа.

2.Откройте REGEDIT.EXE. Если шеф в кабинете, объясните ему, что вам надо запустить на его машине утилиту, которая позволит ему получить доступ

кWeb сервисам XML, над которыми вы работаете (на самом деле не важно, создаете вы Web сервисы XML или нет — одни только эти модные сло вечки заставят босса охотно предоставить вам возможность поковыряться в его машине).

3.В разделе Image File Execution Options создайте раздел OUTLOOK.EXE (за мените его на имя другой почтовой программы, если используется не Microsoft Outlook). Скажите боссу, что вы делаете это для того, чтобы предоставить ему почтовый доступ к Web сервисам XML.

4.Создайте параметр Debugger и введите значение SOL.EXE. Скажите шефу, что SOL нужен для того, чтобы ваши Web сервисы XML получили доступ

кмашинам Sun Solaris.

5.Закройте REGEDIT.EXE.

6.Скажите шефу, что у него все настроено и он может пользоваться Web сервисами XML. Теперь главное — удалиться из кабинета с серьезным

см. след. стр.

154 ЧАСТЬ II Производительная отладка

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

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

Администратор возбудится, потому что теперь он имеет задачу поинте реснее, чем сбрасывать пароли барышням из бухгалтерии. Он будет забав ляться в кабинете шефа с его машиной по меньшей мере день, удерживая таким образом шефа в стороне от машины. Если кто то спросит ваше мне ние, вот готовый ответ: «Я слышал о странностях взаимодействия EJB и NTFS через основы архитектуры DCOM, необходимой для доступа к MFT с исполь зованием алгоритма сортировки методом наименьших квадратов». Админи стратор заберет у шефа его машину и несколько дней будет развлекаться с ней на своем рабочем месте. В конце концов он заменит жесткий диск и переустановит все заново, на что уйдет еще день два. К тому времени, ког да шеф получит свою машину обратно, у него скопится почта за четыре дня, на разбор которой у него уйдет еще минимум один день, а вы можете спо койно игнорировать сообщения еще день или два. Если же почта ШСИ опять начинает учащаться, просто повторите вышеперечисленные шаги еще раз.

Важное замечание: вы используете этот метод на свой страх и риск.

MiniDBG — простой отладчик Win32

На первый взгляд, отладчик Win32 — простая программа, к которой предъявляет ся всего парочка требований. Первое: отладчик должен устанавливать специаль ный флаг DEBUG_ONLY_THIS_PROCESS в параметре dwCreationFlags функции CreateProcess. Этот флаг сообщает ОС, что вызывающий поток должен войти в цикл отладки для управления запущенным процессом. Если отладчик может управлять нескольки ми процессами, порожденными изначальной отлаживаемой программой, он дол жен указывать флаг DEBUG_PROCESS при создании процесса.

Поскольку используется вызов CreateProcess, отладчик и отлаживаемая программа исполняются в разных процессах, благодаря чему устойчивость Win32 систем в процессе отладки весьма высока. Даже если отлаживаемая программа производит беспорядочную запись в память, она все равно не сможет привести к сбою отлад чика. (Отладчики 16 разрядных версий Windows и ОС Macintosh до OS X весьма чувствительны к повреждению отлаживаемых программ, поскольку исполняются в одном процессе с ними.)

ГЛАВА 4 Поддержка отладки ОС и как работают отладчики Win32

155

 

 

Второе требование: после запуска отлаживаемой программы отладчик должен войти в свой цикл путем вызова функции API WaitForDebugEvent для приема отла дочных уведомлений. Завершив обработку некоторого события отладки, он вы зывает ContinueDebugEvent. Имейте в виду, что функции отладочного API могут быть вызваны только тем потоком, что установил специальные флаги отладки при со здании процесса путем вызова CreateProcess. Вот какой небольшой по объему код нужен для создания отладчика Win32:

void main ( void )

{

CreateProcess ( ..., DEBUG_ONLY_THIS_PROCESS ,... ) ;

while ( 1 == WaitForDebugEvent ( ... ) )

{

if ( EXIT_PROCESS )

{

break ;

}

ContinueDebugEvent ( ... ) ;

}

}

Как видите, минимальный отладчик Win32 не требует многопоточности, пользо вательского интерфейса или чего либо еще. И все же, как и в большинстве Windows приложений, разница между минимальным и приемлемым значительна. В действи тельности отладочный API Win32 почти требует, чтобы цикл отладчика работал в отдельном потоке. Как следует из имени, WaitForDebugEvent (ждать события отлад ки) блокирует внутренние события ОС, пока отлаживаемая программа не выпол нит действия, заставляющие ОС остановить исполнение отлаживаемой програм мы, после чего ОС может сообщить отладчику об этом событии. Если отладчик имеет единственный поток, то пользовательский интерфейс полностью заморо жен, пока в отлаживаемой программе не возникнет событие отладки.

Все время в режиме ожидания отладчик принимает уведомления о событиях в отлаживаемой программе. Следующая структура DEBUG_EVENT, заполняемая функцией WaitForDebugEvent, содержит всю информацию о событии отладки (табл. 4 1):

typedef struct _DEBUG_EVENT { DWORD dwDebugEventCode; DWORD dwProcessId;

DWORD dwThreadId; union {

EXCEPTION_DEBUG_INFO Exception;

CREATE_THREAD_DEBUG_INFO CreateThread;

CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;

EXIT_THREAD_DEBUG_INFO ExitThread;

EXIT_PROCESS_DEBUG_INFO ExitProcess;

LOAD_DLL_DEBUG_INFO LoadDll;

UNLOAD_DLL_DEBUG_INFO UnloadDll;

OUTPUT_DEBUG_STRING_INFO DebugString;

156 ЧАСТЬ II Производительная отладка

RIP_INFO RipInfo;

}u;

}DEBUG_EVENT

Табл. 4-1. События отладки

Событие отладки

Описание

CREATE_PROCESS_DEBUG_EVENT Генерируется, когда в рамках отлаживаемого процесса создается новый процесс или когда отладчик начинает отладку уже активного процесса. Ядро системы генери рует это событие отладки до начала выполнения процес са в пользовательском режиме и до того, как ядро гене рирует другие события отладки для нового процесса.

Структура DEBUG_EVENT содержит структуру CREATE_PROCESS_DEBUG_INFO, содержащую описатель нового процесса, описатель файла образа исполняемого про цесса, описатель начального потока процесса и другую информацию, описывающую процесс.

Описатель процесса имеет права доступа PROCESS_VM_READ и PROCESS_VM_WRITE. Если отладчик имеет те же права до ступа к описателю процесса, он может читать память процесса и производить запись в нее через функции

ReadProcessMemory и WriteProcessMemory.

Описатель исполняемого файла процесса имеет права доступа GENERIC_READ и открыт для совместного чтения.

Описатель начального потока процесса имеет права до ступа к потоку THREAD_GET_CONTEXT, THREAD_SET_CONTEXT и THREAD_SUSPEND_RESUME. Если отладчик имеет эти типы до ступа к потоку, он читает регистры потока и записывает в них с помощью функций GetThreadContext и SetThreadContext, а также может приостанавливать поток и возобновлять его исполнение с помощью функций

SuspendThread и ResumeThread.

CREATE_THREAD_DEBUG_EVENT Генерируется, когда в отлаживаемом процессе создается новый поток или когда начинается отладка уже активно го процесса. Это событие отладки генерируется до того, как новый поток начнет свое исполнение в пользова тельском режиме.

Структура DEBUG_EVENT содержит структуру CREATE_THREAD_DEBUG_INFO. Последняя содержит описатель нового потока и его адрес запуска. Описатель имеет пра ва доступа к потоку THREAD_GET_CONTEXT, THREAD_SET_CONTEXT

иTHREAD_SUSPEND_RESUME. Если отладчик имеет эти же пра ва, он может читать регистры потока и записывать в них с помощью функций GetThreadContext и SetThreadContext, а также приостанавливать исполнение потока и возоб новлять его с помощью функций SuspendThread

иResumeThread.

ГЛАВА 4

Поддержка отладки ОС и как работают отладчики Win32

157

 

 

Табл. 4-1. События отладки (продолжение)

 

 

 

 

Событие отладки

Описание

 

EXCEPTION_DEBUG_EVENT

Генерируется, когда в отлаживаемом процессе возникает

 

исключение. Возможные исключения включают попытку

 

обращения к недоступной памяти, исполнение операто

 

ра, на котором установлена точка прерывания, попытку

 

деления на 0 и любые другие исключения, перечислен

 

ные в разделе документации MSDN «Structured Exception

 

Handling» (структурная обработка исключений).

 

 

Структура DEBUG_EVENT содержит структуру EXCEPTION_DE

 

BUG_INFO. Последняя описывает исключение, вызвавшее

 

событие отладки.

 

 

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

 

ний, может происходить дополнительное исключение

 

в процессе отладки консольного приложения. При вводе

 

с консоли Ctrl+C ядро генерирует исключение

 

 

DBG_CONTROL_C для процессов, обрабатывающих в процессе

 

отладки сигнал Ctrl+C. Этот код исключения не предназ

 

начен для обработки в приложениях. Приложение ни

 

когда не должно иметь обработчик этого исключения.

 

Оно нужно только отладчику и применяется, только ког

 

да отладчик присоединен к консольному процессу.

 

 

Если процесс не находится в состоянии отладки или

 

 

если отладчик оставляет исключение DBG_CONTROL_C нео

 

бработанным, производится поиск списка функций об

 

работчиков исключений приложения. (О функциях об

 

работчиках исключений консольного процесса см. доку

 

ментацию MSDN по функции SetConsoleCtrlHandler.)

 

EXIT_PROCESS_DEBUG_EVENT

Возникает, когда завершается последний поток процесса

 

или вызывается функция ExitProcess. Оно возникает сра

 

зу после того, как ядро выгружает все DLL процесса и об

 

новляет код завершения процесса.

 

 

Структура DEBUG_EVENT содержит структуру EXIT_PRO

 

 

CESS_DEBUG_INFO, описывающую код завершения процесса.

 

При возникновении этого события отладчик освобожда

 

ет все внутренние структуры, ассоциированные с про

 

цессом. Описатель, указывающий в отладчике на завер

 

шающийся процесс и описатели всех потоков этого про

 

цесса, закрываются ядром. Отладчик не должен закры

 

вать эти описатели.

 

EXIT_THREAD_DEBUG_EVENT

Возникает, когда завершается поток, являющийся частью

 

отлаживаемого процесса. Ядро генерирует это событие

 

сразу после обновления кода завершения потока.

 

Структура DEBUG_EVENT содержит структуру EXIT_THREAD_DE BUG_INFO, описывающую код завершения потока.

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

см. след. стр.

158

ЧАСТЬ II

Производительная отладка

 

 

Табл. 4-1.

События отладки (продолжение)

 

 

Событие отладки

Описание

 

 

Событие отладки не возникает, если завершающийся

 

 

поток является последним потоком процесса. В этом

 

 

случае вместо него возникает событие отладки

 

 

EXIT_PROCESS_DEBUG_EVENT.

LOAD_DLL_DEBUG_EVENT

Возникает при загрузке DLL отлаживаемым процессом.

 

 

Это событие возникает, когда системный загрузчик раз

решает ссылки на DLL или когда отлаживаемый процесс вызывает функцию LoadLibrary, а также при каждой за грузке DLL в адресное пространство процесса. Если счет чик ссылок на DLL уменьшается до 0, DLL выгружается. При следующей загрузке DLL снова возникает это событие.

Структура DEBUG_EVENT содержит структуру LOAD_DLL_DE BUG_INFO, которая включает описатель файла вновь загру женной DLL, ее базовый адрес и другие данные, описы вающие DLL.

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

OUTPUT_DEBUG_STRING_E VENT Возникает, когда отлаживаемый процесс обращается к функции OutputDebugString.

Структура DEBUG_EVENT содержит структуру OUTPUT_DE BUG_STRING_INFO, которая описывает адрес, размер и фор мат отладочной строки.

UNLOAD_DLL_DEBUG_EVENT Возникает, когда отлаживаемый процесс выгружает DLL с помощью функции FreeLibrary. Это событие возникает только при последней выгрузке DLL из адресного про странства процесса (т. е. когда счетчик ссылок на DLL станет равным 0).

Структура DEBUG_EVENT содержит структуру UNLOAD_DLL_DE BUG_INFO, которая описывает базовый адрес DLL в адрес ном пространстве процесса, выгружающего DLL.

Обычно при получении этого события отладчик выгру жает таблицу символов, ассоциированную с DLL.

При завершении процесса ядро автоматически выгружа ет все DLL процесса, но не генерирует событие отладки

UNLOAD_DLL_DEBUG_EVENT.

При обработке событий отладки, возвращаемых функцией WaitForDebugEvent, отладчик полностью управляет отлаживаемой программой, так как ОС останав ливает все потоки отлаживаемой программы и не управляет ими, пока не вызва на функция ContinueDebugEvent. Если отладчику нужно читать из адресного простран ства отлаживаемой программы или записывать в него, он может вызвать функ ции ReadProcessMemory и WriteProcessMemory. Если память имеет атрибут «только для чтения», можно использовать функцию VirtualProtect, чтобы изменить уровень защиты при необходимости произвести запись в эту часть памяти. Если отладчик редактирует код отлаживаемой программы, используя вызовы функции Write ProcessMemory, надо вызывать функцию FlushInstructionCache для очистки кэша ко

ГЛАВА 4 Поддержка отладки ОС и как работают отладчики Win32

159

 

 

манд для этой части памяти. Если вы забыли вызвать FlushInstructionCache, ваши изменения смогут работать, только если эта память не кэшируется центральным процессором. Если память уже кэширована центральным процессором, измене ния не вступят в силу до повторного считывания в кэш центрального процессо ра. Вызов FlushInstructionCache особенно важен в многопроцессорных машинах. Если отладчику нужно получить или установить текущий контекст отлаживаемой программы или регистров центрального процессора, он может вызвать GetThread Context или SetThreadContext.

Единственным событием отладки Win32, которому требуется особая обработ ка, является точка прерывания загрузчика, или начальная точка прерывания. После того как ОС посылает первые уведомления CREATE_PROCESS_DEBUG_EVENT и LOAD_DLL_DE BUG_EVENT для неявно загруженных модулей, отладчик принимает EXCEPTION_DEBUG_EVENT. Это событие отладки и является точкой прерывания загрузчика. Отлаживаемая программа исполняет эту точку прерывания, так как CREATE_PROCESS_DEBUG_EVENT указывает только, что процесс загружен, а не что он исполняется. Точка прерыва ния загрузчика, которую ОС заставляет сработать при каждой загрузке отлажива емой программы, является тем первым событием, благодаря которому отладчик узнает, что отлаживаемая программа уже исполняется. В настоящих отладчиках инициализация основных структур данных, таких как таблицы символов, проис ходит при создании процесса, и отладчик начинает показывать дизассемблиро ванный код или редактировать код отлаживаемой программы в точке прерыва ния загрузчика.

При возникновении точки прерывания загрузчика отладчик должен зарегист рировать, что он «видел» точку прерывания и может обрабатывать все остальные точки прерывания. Вся остальная обработка первой точки прерывания (а в об щем, и остальных точек) зависит от типа центрального процессора. Для семей ства Intel Pentium отладчик должен продолжить исполнение путем вызова функ ции ContinueDebugEvent с указанием флага DBG_CONTINUE, что позволит продолжить исполнение отлаживаемой программы.

Листинг 4 1 демонстрирует MinDBG — минимальный отладчик, доступный в наборе файлов к этой книге. MinDBG обрабатывает все события отладки и пра вильно исполняет отлаживаемый процесс. Кроме того, он показывает, как присо единиться к существующему процессу и отсоединиться от отлаживавшегося про цесса. Для запуска процесса под MinDBG передайте имя процесса в командной строке с нужными отлаживаемой программе параметрами. Для присоединения к существующему процессу и его отладки, укажите в командной строке десятичный идентификатор процесса, предварив его символом «минус» («–»). Так, если иден тификатор процесса равен 3245, вам надо передать в командной строке –3245, чтобы заставить отладчик присоединиться к этому процессу. Если вы работаете под Windows XP/Server 2003 и более поздними системами, можете отсоединить ся от процесса простым нажатием Ctrl+Break. Имейте в виду, что при работе с MinDBG на самом деле обработчики событий отладки не делают ничего, кроме как показывают некоторую базовую информацию. Превращение минимального отладчика в настоящий потребует значительных усилий.

160 ЧАСТЬ II Производительная отладка

Листинг 4-1. MINDBG.CPP

/*———————— —————————————————————————— ———————— —————————————————————————— Отладка приложений для Microsoft .NET и Microsoft Windows

Copyright (c) 1997 2003 John Robbins — All rights reserved.

Самый простой в мире отладчик программ Win32

—————————————————————————————————————————————————————————————————————— */

/*////////////////////////////////////////////////////////////////////// // Обычные включаемые файлы.

//////////////////////////////////////////////////////////////////////*/

#include "stdafx.h"

/*//////////////////////////////////////////////////////////////////////

//Прототипы и типы.

//////////////////////////////////////////////////////////////////////*/

//Показывает минимальную справку.

void ShowHelp ( void ) ;

// Обработчик нажатия Break.

BOOL WINAPI CtrlBreakHandler ( DWORD dwCtrlType ) ;

// Функции отображения.

void DisplayCreateProcessEvent ( CREATE_PROCESS_DEBUG_INFO & stCPDI ) ;

void

DisplayCreateThreadEvent

( DWORD

dwTID

,

 

 

CREATE_THREAD_DEBUG_INFO & stCTDI

) ;

void

DisplayExitThreadEvent (

DWORD

dwTID

,

 

 

 

EXIT_THREAD_DEBUG_INFO & stETDI

) ;

 

void DisplayExitProcessEvent ( EXIT_PROCESS_DEBUG_INFO & stEPDI ) ;

void DisplayDllLoadEvent (

HANDLE

hProcess ,

 

 

LOAD_DLL_DEBUG_INFO & stLDDI

) ;

void DisplayDllUnLoadEvent

( UNLOAD_DLL_DEBUG_INFO & stULDDI ) ;

void DisplayODSEvent ( HANDLE

hProcess ,

OUTPUT_DEBUG_STRING_INFO &

stODSI

) ;

void DisplayExceptionEvent

( EXCEPTION_DEBUG_INFO

& stEDI ) ;

// Определение типа для DebugActiveProcessStop.

typedef BOOL (WINAPI *PFNDEBUGACTIVEPROCESSSTOP)(DWORD) ;

/*//////////////////////////////////////////////////////////////////////

//Глобальные переменные области видимости файла.

//////////////////////////////////////////////////////////////////////*/

//Флаг, показывающий необходимость отсоединения.

static BOOL g_bDoTheDetach = FALSE ;

/*////////////////////////////////////////////////////////////////////// // Точка входа.

//////////////////////////////////////////////////////////////////////*/

void _tmain ( int argc , TCHAR * argv[ ] )

{

Соседние файлы в предмете Программирование на C++