gdb工具是個頗有用的工具.常常用於咱們項目的調試使用。docker
首先咱們來啓動一個鏡像:sass
docker run -it --privileged=true thrift/new /bin/bash
複製代碼
#include "stdio.h"
int getSum(int param_one,int param_two)
{
return param_one+param_two;
}
int main()
{
int a = 10;
int b = 5;
int sum = getSum(a,b);
printf("%d",sum);
}
複製代碼
使用gcc編譯:bash
gcc -g -o test test.c
複製代碼
加上 -g 選項即爲了程序編譯後的程序中保留調試符號信息數據結構
若是發佈代碼的話,能夠使用命令來移除調試符號信息:函數
strip test
複製代碼
gdb test
#break指令 在main函數處斷點
b main
#在getSum函數處斷點
b getSum
複製代碼
接下來咱們看下執行流程:工具
#run r命令重啓程序將在斷點處停下
r
Breakpoint 1, main () at test.c:10
10 int a = 10;
複製代碼
#continue 繼續向下執行
c
Breakpoint 2, getSum (param_one=10, param_two=5) at test.c:5
5 return param_one+param_two;
複製代碼
咱們看到已經執行到咱們的第二個斷點上來了。ui
固然,還有更加靈活的斷點方式,具體到咱們的代碼某行.spa
#在咱們的例子代碼中,斷點第五行代碼
b test.c:5
Breakpoint 1 at 0x400527: file test.c, line 5.
#運行run
r
Breakpoint 1, getSum (param_one=10, param_two=5) at test.c:5
5 return param_one+param_two;
複製代碼
斷點是爲了更好的調試咱們的程序, 可是咱們發現這樣調試來信息仍是比較少, 若是想了解調用的堆棧信息, 咱們繼續看下面的指令調試
backtrace 命令(簡寫爲 bt)code
(gdb)b test.c:5
(gdb)r
(gdb) bt
#0 getSum (param_one=10, param_two=5) at test.c:5
#1 0x0000000000400556 in main () at test.c:12
複製代碼
咱們看到了調用的堆棧信息 main()->getSum()
函數調用爲棧的數據結構存儲形式
咱們看到只有兩層棧的調用,咱們能夠使用frame切換到指定的棧.
#frame 堆棧編號
f 1
#1 0x0000000000400556 in main () at test.c:12
12 int sum = getSum(a,b);
複製代碼
咱們能夠看到具體的調用方式
# list l 當前斷點處的代碼
#切換棧
(gdb) f 1
(gdb) l
8 int main()
9 {
10 int a = 10;
11 int b = 5;
12 int sum = getSum(a,b);
13 printf("%d",sum);
14 }
複製代碼
#打印params_two的值
p params_two
$1 = 10
複製代碼
咱們還能夠手動修改當前運行變量
p params_two=50
複製代碼
info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400539 in main at test.c:10
2 breakpoint keep y 0x0000000000400527 in getSum at test.c:5
複製代碼
禁用/啓用某個斷點
disable 斷點編號
enable 斷點編號
複製代碼
(gdb) delete
Delete all breakpoints? (y or n) y
複製代碼
(gdb) disassemble
Dump of assembler code for function main:
0x0000000000400531 <+0>: push %rbp
0x0000000000400532 <+1>: mov %rsp,%rbp
0x0000000000400535 <+4>: sub $0x10,%rsp
=> 0x0000000000400539 <+8>: movl $0xa,-0x4(%rbp)
0x0000000000400540 <+15>: movl $0x5,-0x8(%rbp)
0x0000000000400547 <+22>: mov -0x8(%rbp),%edx
0x000000000040054a <+25>: mov -0x4(%rbp),%eax
0x000000000040054d <+28>: mov %edx,%esi
0x000000000040054f <+30>: mov %eax,%edi
0x0000000000400551 <+32>: callq 0x40051d <getSum>
0x0000000000400556 <+37>: mov %eax,-0xc(%rbp)
0x0000000000400559 <+40>: mov -0xc(%rbp),%eax
0x000000000040055c <+43>: mov %eax,%esi
0x000000000040055e <+45>: mov $0x400600,%edi
0x0000000000400563 <+50>: mov $0x0,%eax
0x0000000000400568 <+55>: callq 0x400400 <printf@plt>
0x000000000040056d <+60>: leaveq
0x000000000040056e <+61>: retq
End of assembler dump.
複製代碼
(gdb) b main
(gdb) r
(gdb) watch sum
Old value = 32767
New value = 15
main () at test.c:13
13 printf("%d",sum);
複製代碼
先到這裏吧, 等接下來咱們再研究下多進程的代碼如何使用gdb調試。