原文:
先介紹一下gdb多執行緒除錯的基本命令。info threads顯示當前可除錯的所有執行緒,每個執行緒會有乙個gdb為其分配的id,後面操作執行緒的時候會用到這個id。 前面有*的是當前除錯的執行緒。thread id切換當前除錯的執行緒為指定id的執行緒。break thread_test.c:123 thread all讓所有被除錯執行緒執行gdb命令command。set scheduler-locking off|on|step估計是實際使用過多執行緒除錯的人都可以發現,在使用step或者continue命令除錯當前被除錯執行緒的時候,其他執行緒也是同時執行的,怎麼只讓被除錯 程式執行呢?通過這個命令就可以實現這個需求。off 不鎖定任何執行緒,也就是所有執行緒都執行,這是預設值。 on 只有當前被除錯程式會執行。 step 在單步的時候,除了next過乙個函式的情況(熟悉情況的人可能知道,這其實是乙個設定斷點然後continue的行為)以外,只有當前執行緒會執行。
gdb對於多執行緒程式的除錯有如下的支援:
(gdb) r
starting program: /root/thread
[new thread 1073951360 (lwp 12900)]
[new thread 1082342592 (lwp 12907)]---以下三個為新產生的執行緒
[new thread 1090731072 (lwp 12908)]
[new thread 1099119552 (lwp 12909)]
(gdb) info threads
4 thread 1099119552 (lwp 12940) 0xffffe002 in ?? ()
3 thread 1090731072 (lwp 12939) 0xffffe002 in ?? ()
2 thread 1082342592 (lwp 12938) 0xffffe002 in ?? ()
*1 thread 1073951360 (lwp 12931) main (argc=1, argv=0xbfffda04) at thread.c:21
(gdb)
注意,行首的藍色文字為gdb分配的執行緒號,對執行緒進行切換時,使用該該號碼,而不是上文標出的綠色數字。
另外,行首的紅色星號標識了當前活動的執行緒
(gdb) info threads
4 thread 1099119552 (lwp 12940) 0xffffe002 in ?? ()
3 thread 1090731072 (lwp 12939) 0xffffe002 in ?? ()
2 thread 1082342592 (lwp 12938) 0xffffe002 in ?? ()
* 1 thread 1073951360 (lwp 12931) main (argc=1, argv=0xbfffda04) at thread.c:21
(gdb)thread 4
[switching to thread 4 (thread 1099119552 (lwp 12940))]#0 0xffffe002 in ?? ()
(gdb) info threads
* 4 thread 1099119552 (lwp 12940) 0xffffe002 in ?? ()
3 thread 1090731072 (lwp 12939) 0xffffe002 in ?? ()
2 thread 1082342592 (lwp 12938) 0xffffe002 in ?? ()
1 thread 1073951360 (lwp 12931) main (argc=1, argv=0xbfffda04) at thread.c:21
(gdb)
以上即為使用gdb提供的對多執行緒進行除錯的一些基本命令。另外,gdb也提供對執行緒的斷點設定以及對指定或所有執行緒發布命令的命令。
初次接觸gdb下多執行緒的除錯,往往會忽視gdb中活動執行緒的概念。一般來講,在使用gdb除錯的時候,只有乙個執行緒為活動執行緒,如果希望得到其他的執行緒的輸出結果,必須使用thread命令切換至指定的執行緒,才能對該執行緒進行除錯或觀察輸出結果。
最後介紹一下我最近遇見的乙個多執行緒除錯和解決。
基本問題是在乙個linux環境中,除錯多執行緒程式不正常,info threads看不到多執行緒的資訊。
我先用命令maintenance print target-stack看了一下target的裝載情況,發現target"multi-thread"沒有被裝載,用gdb對gdb進行除錯,發現在 函式check_for_thread_db在呼叫libthread_db中的函式td_ta_new的時候,返回了td_nolibthread,所 以沒有裝載target"multi-thread"。
在時候我就懷疑是不是libpthread有問題,於是檢查了一下發現了問題,這個環境中的libpthread是被strip過的,我想可能 就是以為這個影響了td_ta_new對libpthread符號資訊的獲取。當我換了乙個沒有strip過的libpthread的時候,問題果然解決 了。
最終我的解決辦法是拷貝了乙個.debug版本的libpthread到lib目錄中,問題解決了。
多執行緒如果dump,多為段錯誤,一般都涉及記憶體非法讀寫。可以這樣處理,使用下面的命令開啟系統開關,讓其可以在死掉的時候生成core檔案。
ulimit -c unlimited
這樣的話死掉的時候就可以在當前目錄看到core.pid(pid為程序號)的檔案。接著使用gdb:
gdb ./bin ./core.pid
進去後,使用bt檢視死掉時棧的情況,在使用frame命令。
還有就是裡面某個執行緒停住,也沒死,這種情況一般就是死鎖或者涉及訊息接受的超時問題(聽人說的,沒有遇到過)。遇到這種情況,可以使用:
gcore pid (除錯程序的pid號)
手動生成core檔案,在使用pstack(linux下好像不好使)檢視堆疊的情況。如果都看不出來,就仔細檢視**,看看是不是在if,return,break,continue這種語句操作是忘記解鎖,還有巢狀鎖的問題,都需要分析清楚了。
GDB 除錯多執行緒程式的總結
step就是單步執行,遇到子函式就進入並且繼續單步執行 在其他除錯其中相當於step into命令,作用是移動到下乙個可執行的 行。如果當前行是乙個函式呼叫,則偵錯程式進入函式並停止在函式體的第一行。step可以幫助初步揭開 位置的謎團,例如 函式呼叫和函式本身可能在不同的檔案中。next是在單步執...
GDB除錯多執行緒程式
info threads 顯示當前可除錯的所有執行緒,每個執行緒會有乙個gdb為其分配的id,後面操作執行緒的時候會用到這個id。前面有 的是當前除錯的執行緒。thread id 切換當前除錯的執行緒為指定id的執行緒 break thread test.c 123 thread all 在所有執行...
Gdb 除錯多執行緒程式
gdb多執行緒除錯的基本命令。info threads顯示當前可除錯的所有執行緒,每個執行緒會有乙個gdb為其分配的id,後面操作執行緒的時候會用到這個id。前面有 的是當前除錯的執行緒。thread id切換當前除錯的執行緒為指定id的執行緒。break thread test.c 123 thr...