Перерыв при создании потока в отладчике Visual Studio

Можно ли настроить отладчик Visual Studio на прерывание при создании потока?

(Обратите внимание, что это не то же самое, что прерывание переключения контекста, как было задано в этом другом вопросе:Могу ли я установить точку останова в Visual Studio (c ++) для прерывания при переключении контекста потока?)

 Derek Tomes19 февр. 2013 г., 02:07
Вы когда-нибудь понимали это?
 pauldoo04 мар. 2013 г., 19:17
@ Дерек Томес: я не сделал. Я не работаю с Windows или Visual Studio в эти дни, поэтому я больше не ищу решение самостоятельно.

Ответы на вопрос(6)

Если вы знаете, что поток создается управляемым классом Thread, то простым решением было бы поставить точку останова на его входе (перейдя в окно Breakpoints, щелкнув New-> Break at function и отметив Thread.Start).

В противном случае, как сказал Ганс, вам придется использовать более сложное решение, такое как mdbg, или использовать реализацию CLR-профилировщика с открытым исходным кодом (например,SAE) и помещая инструкцию «asm int 3» в метод ICorProfilerCallback :: ThreadCreated.

Кроме того, если у вас VS2010 Ultimate, вы можете просто найти событие Thread Created в событиях Intellitrace и, возможно, получить от него необходимую информацию (хотя это не прервется при создании потока, а даст некоторую информацию о стек трассировки / значений переменных во время их создания, в ретроспективе).

 Omer Raviv27 дек. 2010 г., 15:07
Связанный намек заключается в том, что при входе в окно инструментов точки останова (Ctrl + Alt + B), при нажатии «Добавить точку останова» и вводе Foo.Foo (где Foo - это имя класса, например, «Thread» или «BackgroundWorker»), он будет помещать точки останова во все конструкторы Foo. ,
 teynon15 авг. 2013 г., 20:12
Просто добавил точку останова дляThread.Start как только мое приложение запустилось, VS поймал его. Тогда у меня не было возможности возобновить работу, и каждый раз, когда я нажимал на VS2010, он говорил мне, что ожидает какого-то процесса. Точка, не добавляйте точку останова, пока ваше приложение не запустится.

Да, отладчик получает уведомление об этом. Нет, пользовательский интерфейс не позволяет вам сказать, что он сломался в этом уведомлении. Если это для управляемого кода, то вы можете использовать пример MDbg и изменить его.

Есть как минимум две потенциальные вещи, которые вы могли бы иметь в виду, когда говорите, что хотите прервать создание потока:

Разрыв внутри создаваемой темы ДО создания новой темыРазбейте поток NEW, прежде чем вызывать пользовательскую функцию.

Для первого варианта вы захотите разбить CreateThread, _beginthread или _beginthreadex.

Что касается второго варианта, вы захотите разбить RtlUserThreadStart или BaseThreadInitThunk, чтобы перехватить новый поток в начале его выполнения до вызова пользовательского кода.

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

Прежде чем начать отладку, в Visual Studio перейдите к инструментам, параметрам, отладке, затем разверните дерево параметров отладки в левой панели. Затем нажмите «родной» и установите флажок «Загрузить экспорт DLL». Затем вы можете снова начать отладку исполняемого файла.

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

{,,} kernel32.dll CreateThread

или же

{,,} ntdll.dll RtlUserThreadStart

Я получил эту информацию, начав здесь:

https://blogs.msdn.microsoft.com/reiley/2011/07/26/debugging-tips-for-multi-threaded-application/

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

 Vinz27 мая 2018 г., 21:29
Первый полезный ответ на эту тему ... Я слишком долго прокручивал для этого. Единственная проблема, с которой я до сих пор сталкиваюсь с вашим объяснением, заключается в том, что точки останова, установленные в соглашении FuncName {,, dll}, по-прежнему не срабатывают. Мне нужно было сделать хакерское копирование указателя, чтобы получить подписи stdcall этих функций, которые затем, казалось, сработали. Не уверен, что это только проблема с моей стороны, однако. Я напишу еще один ответ на тот случай, если кто-то еще об этом узнает.

Я нашел способ сделать это. Погуглив, я увидел противоположный вопрос:Можно ли прервать выход из потока с определенным кодом ошибки?

Я поставил точку останова на функцииRtlExitUserThreadПосле этого я понял, что все потоки создаются с помощью функцииRtlUserThreadStartтак что поставьте другую точку останова для этой функции и все :)

 Min30 мая 2018 г., 23:55
В Visual Studio в окне Точки останова (Debug / Windows / Breakpoints или Alt + F9) вы можете установить точки останова для символов функций. Нажмите «Создать» / «Функции Точка останова ...» или Ctrl + B в окне Точки останова и введите имя функции в диалоговом окне, в данном случае RtlUserThreadStart. Для меня это работает даже без загрузки символов Microsoft ntdll.pdb.
 Vinz27 мая 2018 г., 20:51
Вы не могли бы остановиться на том, какименно так вы "поставили точку останова в функции RtlUserThreadStart"? Кажется, я не могу поставить какие-либо точки останова на внутренние функции DLL Windows, даже с методами, описанными в других сообщениях.
 Vinz31 мая 2018 г., 19:25
Хорошо, это странно. Я включил экспорт и символы и никогда не делал точки останова наRtlUserThreadStart ударил ... Однако я смог найти его подпись stdcall, на которую успешно работает отладчик. Также спасибо Visual Studio за то, что она не выдает никаких сообщений об ошибках, когда создание новой точки останова по какой-то причине не удается.

Как объясняет @George, есть две функции, которые вы можете использовать. Если вы хотите узнатьчто создает новую тему Вы должны прервать поток, создавая вызовы функций WINAPI, такие какCreateThread или же_beginthread(ex), Если вы хотите разбить начало вновь созданного потока (в стеке вызовов этого потока), вам следуетRtlUserThreadStart.

Тем не менее, есть две предпосылки, чтобы можно было взломать любой из них:

1. Загрузка символов с серверов Microsoft должна быть включена

Чтобы точки останова работали, отладчику необходимо знать некоторую базовую информацию о символах собственных библиотек DLL. Убедитесь, что загрузка символов с серверов MS включена (Сервис -> Параметры -> Отладка -> Символы)

2. Вам нужны фактические подписи stdcall целевых функций

По какой-то причине даже при включенной загрузке экспорта VS не смог найти функции, которые мне нужно было взломать. Итак, я проверил, какие настоящие подписи. Это можно сделать с помощьюутилита dumpbin cmd line VSили запустив короткий тест по коду:

void* ptr = CreateThread;

Запуск этого кода в отладчике показывает адрес и подписьCreateThread например, который[email protected] для меня (Win7 32-битное приложение). ЗаRtlUserThreadStart это было[email protected] для меня.

3. Установка точки останова

Теперь это так же просто, как выбрать Debug -> New Breakpoint -> Break at Function. Для имени функции, которую вы ставите либо[email protected] или же[email protected] а остальное оставь.

Это тогда срабатывает, когда создается новый поток.

наблюдение

[email protected] похоже, что он охватывает функции CreateThread, _beginthread и _beginthreadex.

Вы можете установить точку останова при первом вызовеCreateThread (может быть, вы вставили поддельный вызов для этой цели). Когда нажмете, перейдите из режима просмотра исходного кода в режим просмотра дизассемблирования и перейдите к вызову. Пройдите через ImportLib-код и установите точку останова. Не идеально, но это работает.

Ваш ответ на вопрос