Linux/Windows下C++设置线程名字方便多线程调试

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/FlushHip/article/details/83017137

C++多线程编程,调试是一个大问题,原因之一就是,线程名字继承了父进程的名字,因此导致同一段代码的不同线程名字一样;而且还会导致线程的名字怪怪的,不好看。

因此,如果在代码中可以设置线程的名字就好了,这样在调试中就可以看到期望的线程名字,这样便于调试。

由于编写跨平台代码,因此,线程设置名字对Windows和Linux来说都很重要,这里分别来讲下。

Windows

在Visual Studio调试的线程选项卡看到设置名字后的线程的名字:
在这里插入图片描述

可以看到,我把其中一条线程的名字改成了FlushHip-TEST-THREAD,要是没有设置,会是怎么样的呢,看下图:
在这里插入图片描述
看到了吧,这样的名字只有老天知道是哪条线程。

那么在Windows中如何用代码来设置线程名字呢?

#include <windows.h>

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;

void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
{
    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = szThreadName;
    info.dwThreadID = dwThreadID;
    info.dwFlags = 0;

    __try
    {
        RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
    }
    __except(EXCEPTION_CONTINUE_EXECUTION)
    {
    }
}

利用结构化异常SHE和RaiseException还有异常代码0x406D1388,可以实现设置线程名字。

The native method of setting the thread name is implemented by raising an SEH exception that is continued. If you go to the docs on RaiseException you’ll see part of the reason for this strange mechanism. An attached native debugger will get a ‘first chance’ notification of the exception. Raising an exception is precisely what you need to do to get the native debugger’s attention. The one raised here (0x406D1388) is recognized by VS (and WinDbg).

SHE是编译期相关的,这样子设置线程名字的方式只能用于VS。

如何使用这个函数呢?首先,在本线程中设置名字只需要把dwThreadID设置成-1就行了,设置别的线程的名字可以指定别的线程的ID。

std::thread th([]()
{
    SetThreadName(-1, "FlushHip-TEST-THREAD");
    std::this_thread::sleep_for(std::chrono::seconds(1000));
});

Linux

Linux下可以使用prctlpthread_setname_np来设置线程名字,注意,这个设置线程名字是真的会设置线程名字。在Linux下我们可以通过下面两种方式来看看线程的名字

  • cat /proc/pid/task/[tid]/comm
  • ps ps -eL -o lwp,comm | grep tid

也来看看设置前和设置后的效果:

在这里插入图片描述

在这里插入图片描述

可以看到设置前,主线程和辅助线程都是同一名字,无法分辨,但是,设置后,可以很明显看到差别,且,我设置的线程名字是FlushHip-TEST-THREAD,但是显示出来的只有FlushHip-TEST-T,这是因为Linux下利用prctlpthread_setname_np来设置线程名字,而这两个函数的man手册中明确指出了,线程名字最多支持16个字节的空间,FlushHip-TEST-T是15个字符,还有结尾的\0,刚好16个字符。

长度限制也是Linux设置线程名字的一个短板,因此,在设置线程名字的时候尽量精简一些。看看代码实现:

#include <sys/prctl.h>
#include <pthread.h>

void SetThreadName(pthread_t thread, const char *name)
{
    if (thread == -1)
        prctl(PR_SET_NAME, name)
    else
        pthread_setname_np(thread, name);
}

我们可以在GDB下打上断点,用info threads看看实际效果:

在这里插入图片描述

这样子调试多线程的时候就方便很多了。


参考:

猜你喜欢

转载自blog.csdn.net/FlushHip/article/details/83017137