GDB 調試多線程程序的總結


gdb 中step、next與finish的區別

step 就是單步執行,遇到子函數就進入並且繼續單步執行;在其他調試其中相當於step-into命令,作用是移動到下一個可執行的代碼行。如果當前行是一個函數調用,則調試器進入函數並停止在函數體的第一行。step可以幫助初步揭開代碼位置的謎團,例如:函數調用和函數本身可能在不同的文件中。

next 是在單步執行時,在函數內遇到子函數時不會進入子函數內單步執行,而是將子函數整個執行完再停止,也就是把子函數整個作為一步。在其他調試器中相當於step-over,作用是在同一個調用棧層中移動到下一個可執行的代碼行。調試器不會進入函數體。如果當前行是函數的最后一行,則,next將進入下一個棧層,並在調用函數的下一行停止。

finish 就是但單步執行到子函數內時,用step out就可以執行完子函數余下部分,並返回到上一層函數。在其他調試器中相當於step-out,作用是在棧中前進到到下一層,並在調用函數的下一行停止。

多線程的gdb調試

假設現在有一個主線程創建了一個子線程。

gdb調試時,設置斷點,單步調試到pthread_create處的時候,這時候會創建子線程,會出現如下信息

[New Thread 0x7ffff6fd1700 (LWP 6376)]

默認情況下,gdb只跟蹤主線程,新創建的線程都被阻塞在pthread_create函數處。

info threads 可以調試的所有線程,gdb會為每個線程分配一個ID,這個ID和線程ID不同,ID號一般從1開始。

如下,表示當前有兩個線程1和2,*表示跟蹤主線程1

(gdb) info threads
  Id   Target Id         Frame 
  2    Thread 0x7ffff6fd1700 (LWP 6376) "test" 0x00007ffff70d0851 in clone ()
   from /lib64/libc.so.6
* 1    Thread 0x7ffff7fee740 (LWP 6375) "test" main (argc=1, argv=0x7fffffffe2d8) at test.cpp:31

thread ID 切換當前調試的線程為指定ID號,ID是gdb分配的序號,不是線程TID。

set scheduler-locking off|on on鎖定其他線程,只有當前選擇調試的線程執行,off表示不鎖定任何線程,當運行到斷點處,將所有的線程都暫停下來,直到指定某個線程繼續執行,如果在當前線程下使用continue的話會啟動所有線程(GDB默認)。

多線程調試控制指令

thread apply ID1 ID2 ...IDn gdb_command 指定多個線程執行gdb中的command指令

thread apply all command 指定所有線程執行gdb中的command指令

non-stop模式

上面說過一個線程中斷在一個斷點上,其他所有的線程都會被freeze。新版本的GDB中,引入了non-stop模式,在這個模式下:

  1. 當某個或多個線程在一個斷點上,其他線程仍會並行運行

  2. 你可以選擇某個被中斷的線程,只讓他運行。

  3. non-stop模式表示不停止模式,除了斷點有關的進程會被停下來,其他線程會繼續執行。

設置non-stop模式,打開gdb后,在開始r之前,首先連續輸入下面的指令

set target-async 1
set pagination off
set non-stop on

總結調試多線程的命令

info threads 顯示當前可調試的所有線程,每個線程會有一個GDB為其分配的ID,后面操作線程的時候會用到這個ID。 前面有*的是當前調試的線程

thread ID(1,2,3…) 切換當前調試的線程為指定ID的線程

break thread_test.c:123 thread all(例:在相應函數的位置設置斷點break pthread_run1) 在所有線程中相應的行上設置斷點

thread apply ID1 ID2 command 讓一個或者多個線程執行GDB命令command

thread apply all command 讓所有被調試線程執行GDB命令command

set scheduler-locking 選項 command 設置線程是以什么方式來執行命令

set scheduler-locking off 不鎖定任何線程,也就是所有線程都執行,這是默認值

set scheduler-locking on 只有當前被調試程序會執行

set scheduler-locking on step 在單步的時候,除了next過一個函數的情況(熟悉情況的人可能知道,這其實是一個設置斷點然后continue的行為)以外,只有當前線程會執行

線程池調試技巧

調試進程池和線程池中的程序一個不錯的方法,是將池中的個數減少至1,觀察是否正確,然后逐步增加線程數量,調試線程的同步是否正確


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM