Каков наилучший способ присоединить отладчик к процессу в VC ++ в нужный момент времени? - PullRequest
7 голосов
/ 19 марта 2009

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

Обычно я выполняю вызов Sleep () или MessageBox, чтобы было проще подключить отладчик. Я волнуюсь, что некоторые из них могут быть в конечном итоге переданы в систему контроля версий.

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

Охрана Сна или окна сообщения с #ifdef _DEBUG - это один из способов, но мне интересно, есть ли лучший способ.

Во время сна у вас также есть проблема, которую вы не можете вовремя приложить. С MessageBox у вас есть проблема, связанная с удаленной отладкой или отладкой процесса, у которого нет видимого графического интерфейса (например, в качестве службы в Vista)

Ответы [ 7 ]

11 голосов
/ 19 марта 2009
9 голосов
/ 19 марта 2009

Чтобы прикрепить отладчик к определенной точке, у вас есть несколько вариантов:

Самое простое - просто вызвать DebugBreak, что в значительной степени эквивалентно __asm int 3, но также работает на других архитектурах (MSVC для x64 не позволяет встроенную сборку, если я правильно помню). Это откроет окно отладчика точно в срок, и вы сможете выбрать из зарегистрированных отладчиков (например, Visual Studio) для подключения к процессу.

Кроме того, вы можете ввести вызов на Sleep, что даст вам возможность подключить отладчик. Вы должны использовать #ifdef _DEBUG для этого, чтобы гарантировать, что вы на самом деле не отправляете с этим кодом.

Один вопрос: почему вы не можете запустить код из IDE? Это служба или DLL-библиотека, загруженная IIS, или аналогичная?

В этом случае вы можете получить ключ реестра ImageFileExecutionOptions, который позволяет подключить отладчик в момент запуска процесса.

Если вы используете для этого cdb, вы можете настроить его как сервер или клиент для экземпляра WinDbg и выполнить отладку таким образом. Я делал это в прошлом, используя WinDbg в качестве отладчика ядра и используя ImageFileExecutionOptions для запуска ntsd -d с указанным процессом. Это заставляет WinDbg переходить в режим пользователя. Иногда это полезная техника.

7 голосов
/ 26 января 2016

другой вариант, который я иногда использую, это

while( !::IsDebuggerPresent() )
    ::Sleep( 100 ); // to avoid 100% CPU load

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

6 голосов
/ 19 марта 2009

Фредди и Реоа имеют правильные решения. Но я хотел добавить причину, почему бы не использовать MessageBox.

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

  1. Общается через сообщения Windows
  2. Имеет нетривиальный интерфейс
  3. Многопоточный

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

Недавно мы внесли изменения в нашу базу кода, чтобы никогда не показывать MessageBox, чтобы облегчить разрыв по этой самой причине. Это приводит к очень плохому поведению для нетривиального приложения.

2 голосов
/ 19 марта 2009

Привязка в «правильной точке» - это боль ... один из вариантов - это просто указать в коде операторы DebugBreak (), чтобы вызвать проблему, и было бы неплохо защитить их с помощью #ifdef _DEBUG. Мы используем макрос ASSERT, который может вызывать DebugBreak (), поэтому вы можете просто написать ASSERT (false)

Другой вариант, который следует рассмотреть, - это использовать «опции исполнения файла изображения» для автоматического запуска отладчика. См. Этот блог и MSDN документацию.

1 голос
/ 19 марта 2009
__asm int 3 

Эта жесткая точка останова вызовет диалог отладки, который позволит вам присоединиться к процессу. Оберните это в #ifdef _DEBUG, и вы попадете в него только в отладочных сборках.

1 голос
/ 19 марта 2009

Смотри вверх:

DebugBreak, __debugbreak и друзья

или

static void timeToChase () {__asm ​​{int 3; }; }

...