Советы для отладки потоков
В этой статье содержатся полезные сведения об отладке потоков, включая сведения о настройке имен потоков для машинного и управляемого кода.
Советы по C/C++
Ниже приведены некоторые советы по отладке потоков в машинном коде.
Можно просмотреть содержимое блока информации потока, введя
@TIB
в окно Контрольные значения или диалоговое окно Быстрая проверка.Можно просмотреть код последней ошибки текущего потока, введя
@Err
в окно Контрольные значения или диалоговое окно Быстрая проверка.Для отладки многопоточного приложения можно использовать функции библиотеки времени выполнения C (CRT). Дополнительные сведения см. в разделе _malloc_dbg.
Задание имени потока в C/C++
Именование потоков можно выполнить в любом выпуске Visual Studio. Именование потоков позволяет находить необходимые потоки в окне Потоки при отладке выполняемого процесса. Наличие распознаваемых именованных потоков также может оказаться полезным при выполнении последующей отладки с помощью проверки аварийного дампа и при анализе записей производительности с помощью различных средств.
Способы задания имени для потока
Имя для потока можно задать одним из двух способов. Во-первых, с помощью функции SetThreadDescription. Во-вторых, создав определенное исключение, когда отладчик Visual Studio подключается к процессу. Каждый подход имеет свои преимущества и недостатки. Использование SetThreadDescription
поддерживается начиная с Windows 10 версии 1607 или Windows Server 2016.
Следует отметить, что оба подхода можно использовать вместе, если это необходимо, так как механизмы, с помощью которых они работают, не зависят друг от друга.
Задание имени для потока с помощью функции SetThreadDescription
Преимущества:
- Имена потоков отображаются при отладке в Visual Studio независимо от того, был ли отладчик присоединен к процессу во время вызова функции SetThreadDescription.
- Имена потоков отображаются при выполнении отладки после аварийного завершения путем загрузки аварийного дампа в Visual Studio.
- Имена потоков отображаются и при работе с другими средствами, такими как отладчик WinDbg и анализатор производительности Windows Performance Analyzer.
Предупреждения:
- Имена потоков отображаются только в Visual Studio 2017 версии 15.6 и более поздних версий.
- При отладке файла аварийного дампа после аварийного завершения имена потоков отображаются только в том случае, если сбой произошел в Windows 10 версии 1607, Windows Server 2016 или более поздних версиях Windows.
Пример:
#include <windows.h>
#include <processthreadsapi.h>
int main()
{
HRESULT r;
r = SetThreadDescription(
GetCurrentThread(),
L"ThisIsMyThreadName!"
);
return 0;
}
Задание имени для потока путем создания исключения
Другой способ задать имя потока в программе — передать требуемое имя потока отладчику Visual Studio путем создания специально настроенного исключения.
Преимущества:
- Работает во всех версиях Visual Studio.
Предупреждения:
- Работает только в том случае, если отладчик был подключен в момент применения метода исключений.
- Имена потоков, заданные с помощью этого метода, не будут доступны в дампах или средствах анализа производительности.
Пример:
Представленная ниже функция SetThreadName
демонстрирует метод исключений. Обратите внимание на то, что имя потока автоматически копируется в поток, чтобы можно было освободить память для параметра threadName
после того, как вызов функции SetThreadName
будет завершен.
//
// Usage: SetThreadName ((DWORD)-1, "MainThread");
//
#include <windows.h>
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void SetThreadName(DWORD dwThreadID, const char* threadName) {
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
__try{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_EXECUTE_HANDLER){
}
#pragma warning(pop)
}
Установка имени потока в управляемом коде
Именование потоков можно выполнить в любом выпуске Visual Studio. Именование потоков позволяет отслеживать их в окне Потоки.
Чтобы задать имя потока в управляемом коде, используйте свойство Name.
Пример
public class Needle
{
// This method will be called when the thread is started.
public void Baz()
{
Console.WriteLine("Needle Baz is running on another thread");
}
}
public void Main()
{
Console.WriteLine("Thread Simple Sample");
Needle oNeedle = new Needle();
// Create a Thread object.
System.Threading.Thread oThread = new System.Threading.Thread(oNeedle.Baz);
// Set the Thread name to "MyThread".
oThread.Name = "MyThread";
// Starting the thread invokes the ThreadStart delegate
oThread.Start();
}