1. 程式人生 > 實用技巧 >GDB多執行緒多程序除錯

GDB多執行緒多程序除錯

gdb多執行緒除錯
gdb提供的多執行緒除錯工具
新執行緒建立自動提醒
thread thread-id實現不同執行緒之間的切換
info threads查詢存在的執行緒
thread apply [thread-id-list] [all] args在一系列執行緒上執行命令
執行緒中設定指定的斷點
set print thread-events控制列印執行緒啟動或結束是的資訊
set scheduler-locking off|on|step在使用step或是continue進行除錯的時候,其他可能也會並行的執行,如何才能夠只讓被除錯的執行緒執行呢?該命令工具可以達到這個效果。
off:不鎖定任何執行緒,也就是所有的執行緒都執行,這是預設值。
on:只有當前被除錯的執行緒能夠執行。
step:阻止其他執行緒在當前執行緒單步除錯時,搶佔當前執行緒。只有當next、continue、util以及finish的時候,其他執行緒才會獲得重新執行的機會。
示例程式碼

include

include <pthread.h>

include

void* threadPrintHello(void* arg)
{
while(1)
{
sleep(5);
std::cout << "hello" << std::endl;
}
}

void* threadPrintWorld(void* arg)
{
while(1)
{
sleep(5);
std::cout << "world" << std::endl;
}
}

int main( int argc , char* argv[])
{
pthread_t pid_hello , pid_world;

int ret = 0;

ret = pthread_create(&pid_hello , NULL , threadPrintHello , NULL);

if( ret != 0 )
{
    std::cout << "Create threadHello error" << std::endl;
    return -1;
}

ret = pthread_create(&pid_world , NULL , threadPrintWorld , NULL);

if( ret != 0 )
{
    std::cout << "Create threadWorld error" << std::endl;
    return -1;
}

while(1)
{
    sleep(10);
    std::cout << "In main thread"  << std::endl;
}

pthread_join(pid_hello , NULL);
pthread_join(pid_world , NULL);

return 0;

}
執行緒建立提醒
在GNU/Linux上,如果gdb檢測一個新的執行緒,會給出如下通知

[New Thread 0x7ffff708b700 (LWP 20567)]
[New Thread 0x7ffff688a700 (LWP 20568)]
查詢已經存在的執行緒
使用info threads可以看到程式中所有執行緒的資訊

(gdb) info threads
3 Thread 0x7ffff688a700 (LWP 20568) 0x00007ffff70be8e0 in sigprocmask () from /lib64/libc.so.6
2 Thread 0x7ffff708b700 (LWP 20567) 0x00007ffff7138a3d in nanosleep () from /lib64/libc.so.6

  • 1 Thread 0x7ffff7fe5720 (LWP 20564) main (argc=1, argv=0x7fffffffe628) at multithreads.cpp:39
    主要包括gdb分配的執行緒id號(例如1,2,3),作業系統分配的執行緒id(例如20568),執行緒的名字以及執行緒相關的呼叫棧資訊。

切換執行緒
thread threadno可以切換到指定的執行緒,threadno就是上面gdb分配的執行緒id號。

(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff708b700 (LWP 20567))]#0 0x00007ffff7138a3d in nanosleep () from /lib64/libc.so.6
鎖定一個執行緒
預設情況下gdb不鎖定任何執行緒

(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff708b700 (LWP 20567))]#0 threadPrintHello (arg=0x0) at multithreads.cpp:10
10 std::cout << "hello" << std::endl;
(gdb) n
helloworld

In main thread
7 while(1)
(gdb) n
9 sleep(5);
(gdb) n
world
In main thread
10 std::cout << "hello" << std::endl;
當我們切換到執行緒2的時候,使用next執行的時候,發現列印的結果中包含有其他執行緒的列印資訊。

可以使用set scheduler-locking on來鎖定只有當前的執行緒能夠執行。

(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff708b700 (LWP 20567))]#0 threadPrintHello (arg=0x0) at multithreads.cpp:10
10 std::cout << "hello" << std::endl;
(gdb) set scheduler-locking on
(gdb) n
hello
7 while(1)
(gdb) n
9 sleep(5);
(gdb) n
10 std::cout << "hello" << std::endl;
(gdb) n
hello
7 while(1)
(gdb) n
9 sleep(5);
(gdb) n
10 std::cout << "hello" << std::endl;
可以發現鎖定執行緒之後,使用next執行變不會有其它執行緒的列印結果。

執行命令
使用thread apply來讓一個或是多個執行緒執行指定的命令。例如讓所有的執行緒列印呼叫棧資訊。