一、gdb基礎知識
1、gdb是Linux環境下的一種調試工具,使用時在源程序生成是加上-g選項。
2、開始使用:gdb binFile;退出使用:ctrl+d或quit。
3、調試過程中常用的命令有:
(1)list命令
list linenum 顯示程序第linenum行周圍的程序
list function 顯示函數名爲function的函數的源程序
list 顯示當前行後面的源程序
list - 顯示當前行前面的源程序
(2)run(r)運行命令
run args run命令可以直接接命令行參數值,也可以在執行run之前通過set args +參數值實現。
(3)break(b)打斷點
b linenum 在某行打斷點
b +offset/-offset 在當前行號的前面或後面offset停住
b filename:linenum 在某文件的某行打斷點
b filename:function 在某文件某個函數入口停住
b *address 在程序的運行地址處停住
b 沒有參數再下一句停住
b where if cindition 在某個條件滿足時,在某行停止
關閉斷點:delete(d)bresakpoint-id
(4)單步命令
step count 一次性執行count步,如果有函數hiu進入函數
next count 一次性執行count,不進入函數
finish 運行程序,直到當前函數完成返回,並打印函數返回時的堆棧地址和返回值以及參數信息
until 退出循環體
(5)continue命令
當程序被停住之後,可以使用continue(c)命令,恢復程序的運行知道程序結束或到達下一個斷點。這裏要注意如果沒有斷點程序是會直接結束的
(6)print(p)命令
這個命令比較常用,用來查看我們想看的內容。比如有關數組可以看全部,也可以從左到右某一部分:
print命令針對變量查看的輸出格式有:
x 按十六進制格式顯示變量
d 按十進制格式顯示變量
u 按十六進制格式顯示無符號整型
o 按八進制格式顯示變量
t 按二進制格式顯示變量
a 按字符格式顯示變量
......
(7)watch命令
watch expr 爲表達式expr設置一個觀察點,一旦表達式值有變化,馬上停住程序
rwatch expr 當表達式expr被讀時。停住程序
awatch expr 當表達式的值被讀或被寫時,程序停住
info watchpoints 列出所有觀察點(info指令通常可以去套)
(8)examine命令
x/u addr 查看內存中的值,“x/”後的n、f、u都是可選項
(9)jump命令
jump命令不會改變程序棧的內容,一般只在同一函數內跳轉
jump linespec 指定下一跳語句的運行點,linespec可以是linenum,filename+linenum,+offset這幾種形式
jump address 跳到代碼行的地址
(10)ignal命令
使用signal信號名(如SIGINT)這種方式把信號發送給程序,如果程序註冊了signal_handler函數,還可以進行相應的處理,幫助調試程序
(11)set命令
set args 設置命令行參數
set env environmentVarname=value設置環境變量。
(12)call命令
call function 強調調用某函數
強調調用某函數,它會顯示函數返回值(如果函數返回值不是void)。print命令也可以完成該功能。
(13)disassemble命令
反彙編命令,查看執行時源代碼的機器碼
二、使用gdb調試多進程
1、代碼調試:
2、gdb可以同時調試多個程序。
只需設置follow-fork-mode(默認值:parent)和detach-on-fork(默認值:on)即可。
parent on 只調試主進程(gdb默認)
child on 只調試子進程
parent off 同時調試兩個進程,gdb和主程序,子進程block在fork位置
child off 同時調試兩個進程,gdb和子進程,主進程block在fork位置
3、進入gdb調試模式
4、查看系統默認的follow-fork-mode和detach-on-fork
5、設置follow-fork-mode和detach-on-fork
6、用list命令查看源代碼(按enter翻頁),分別在子進程和父進程相應位置下斷點
7、打斷點
8、查看正在調試的進程:
顯示gdb調試的所有inferior,gdb會爲它們分配id。其中帶有*得進程是正在調試的inferior。(gdb將每一個被調試程序的執行記錄在一個名爲inferior的結構中。一般情況下一個inferior對應一個進程,每個不同inferior有不同的地址空間。inferior有時候會在進程沒有啓動的時候就存在。)
9、切換調試的進程:inferior<infer number>
10、其他
(1)remove-inferior infno
刪除一個infno號的inferior。如果inferior正在運行則不能刪除,所以刪除前需要先kill或者detach這個inferior。
(2)clone-inferior[-copies n] [infno]
複製n個編號是infno號的inferior。如果指不定n的話,就只複製一個inferior。如果不指定infno,則就複製正在調試的inferior。
(3)detach inferior
detach掉編號是infno的inferior。注意這個inferior還存在,可以再次用run命令執行它。
(4)kill inferior infno:
kill掉infno號inferior。注意這個inferior任然存在,可以再次用run等命令執行它。
(5)set schedule-multiple on|off
設爲off:只有當前inferior會執行。
設爲on:全部是執行狀態inferior都會執行。
這個選項類似於多線程裏的set。
(6)main info program-space
顯示當前gdb一共管理多少地址空間
(7)set print inferior-events on|off
打開和關閉inferior狀態的提示信息
show print inferior-events
查看print inferior-events設置的狀態
(8)set follow-exec-mode new|same
設置same:當發生exec的時候,在執行exec的inferior上控制子進程。
設置爲new:新建一個inferior給執行的子進程。而父進程的inferior任然保留,當前保留的inferior的程序狀態是沒有執行。
三、gdb調試多線程
1、調試代碼
上面代碼中主進程創建了3個子進程,他們是thread1,thread2和thread3,所以也就有3的線程。
2、使用gdb對多線程進行調試
gdb調試多線程的的常用命令:
(1)info threads 顯示可以調試的所有線程
gdb會爲每個線程分配一個id(和tid不同),編號一般從1開始。後面的id是指它的id。
(2)thread id 切換當前調試的線程·爲指定id的線程
(3)break FileName.cpp:LineNum thread all:
所有線程都在文件FineName.cpp的第Linenum行有斷點
(4)step:在step(單步)調試時,只有被調試的線程運行
(5)set non-stop on/off
當調試一個線程時,其它線程是否運行。
set pagination on/off
在使用backtrack時,在分頁時是否停止
set target-async on/off:
同步和異步。同步,gdb在輸出提示符之前等待程序報告一些線程已經終止的信息。而異步的則直接返回
show scheduler-locking
查看當前鎖定線程的模式