https://zhuanlan.zhihu.com/p/46605905
1.gdb filename 直接调试目标文件
2.gdb attach pid 附加已运行的进程
不想影响当前的进程,输入detach与进程分离
3.gdb filename corename 调试core文件
需要开启core文件生成
ulimit -a
core file size (blocks, -c) 0
说明是关闭状态
开启:ulimit -c unlimited 加入到.profile中
source .profile
ulimit -a是否生效
一般core文件生成所在目录都是在程序运行目录
sudo vi /etc/sysctl.conf
mkdir /home/log/core_dump
kernel.core_pattern=/home/log/core_dump/core-%e-%p-%t
%e:执行文件名称
%p:pid
%t:dump时间
配置修改生效
sudo sysctl -p /etc/sysctl.conf
调试命令
run r 运行一个程序
continue c 让暂停的程序继续运行
next n 运行到下一行
step s 如果有调用函数,进入调用的函数内部,相当于 step into
until u 运行到指定行停下来
finish fi 结束当前调用函数,到上一层函数调用处
return return 结束当前调用函数并返回指定值,到上一层函数调用处
jump j 将当前程序执行流跳转到指定行或地址
print p 打印变量或寄存器值
backtrace bt 查看当前线程的调用堆栈
frame f 切换到当前调用线程的指定堆栈,具体堆栈通过堆栈序号指定
thread thread 切换到指定线程
break b 添加断点
tbreak tb 添加临时断点
delete del 删除断点
enable enable 启用某个断点25
disable disable 禁用某个断点
watch watch 监视某一个变量或内存地址的值是否发生变化
先打印出变量的地址:print &var,watch *(int*)0x1234
list l 显示源码
info info 查看断点 / 线程等信息
ptype ptype 查看变量类型
disassemble dis 查看汇编代码
set args 设置程序启动命令行参数
show args 查看设置的命令行参
break添加断点方式
1.break functionname:在函数名为 functionname 的入口处添加一个断点
2.break LineNo:在当前文件行号为 LineNo 处添加一个断点
3.break functionname:LineNo 在 filename 文件行号为 LineNo 处添加一个断点
bt(backtrace):查看堆栈信息
frame num(堆栈编号):查看对应的堆栈编号,进行堆栈编号切换
(gdb) frame 5
#5 0x0807d535 in main (argc=1, argv=0xbffff244) at server.c:5128
查看断点
info break/info breakpoints
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0807cf3a in main at server.c:4969
breakpoint already hit 1 time
2 breakpoint keep y 0x08070862 in anetListen at anet.c:455
breakpoint already hit 1 time
3 breakpoint keep y 0x080708b1 in anetListen at anet.c:458
4 breakpoint keep y 0x08070903 in anetListen at anet.c:464
5 breakpoint keep y 0x0807090a in anetListen at anet.c:466
breakpoint already hit 1 time
disable 断点编号:禁用断点编号
(gdb) disable 1
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep n 0x0807cf3a in main at server.c:4969
breakpoint already hit 1 time
2 breakpoint keep y 0x08070862 in anetListen at anet.c:455
breakpoint already hit 1 time
3 breakpoint keep y 0x080708b1 in anetListen at anet.c:458
4 breakpoint keep y 0x08070903 in anetListen at anet.c:464
5 breakpoint keep y 0x0807090a in anetListen at anet.c:466
breakpoint already hit 1 time
enable 断点编号:启用断点编号
disable:不加断点编号,则禁用所有断点编号
(gdb) disable
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep n 0x0807cf3a in main at server.c:4969
2 breakpoint keep n 0x08070862 in anetListen at anet.c:455
breakpoint already hit 1 time
3 breakpoint keep n 0x080708b1 in anetListen at anet.c:458
4 breakpoint keep n 0x08070903 in anetListen at anet.c:464
5 breakpoint keep n 0x0807090a in anetListen at anet.c:466
breakpoint already hit 1 time
enable:不加断点编号,则启用所有断点编号
(gdb) enable
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0807cf3a in main at server.c:4969
2 breakpoint keep y 0x08070862 in anetListen at anet.c:455
breakpoint already hit 1 time
3 breakpoint keep y 0x080708b1 in anetListen at anet.c:458
4 breakpoint keep y 0x08070903 in anetListen at anet.c:464
5 breakpoint keep y 0x0807090a in anetListen at anet.c:466
breakpoint already hit 1 time
delete 断点编号:删除断点
(gdb) delete 2 3
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x0807cf3a in main at server.c:4969
4 breakpoint keep y 0x08070903 in anetListen at anet.c:464
5 breakpoint keep y 0x0807090a in anetListen at anet.c:466
breakpoint already hit 1 time
delete:不加断点编号,则删除所有断点
list命令
(gdb) list
如果不带任何参数的话,该命令会接着打印上次 list 命令打印出代码后面的代码。如
果是第一次执行 list 命令则会显示当前正在执行代码位置附近的代码。
(gdb) list -
如果参数是一个减号的话,则和前面刚好相反,会打印上次 list 命令打印出代码前面
的代码。
(gdb) list LOATION
list 命令还可以带一个代码位置作为参数,顾名思义,这样的话就会打印出该代码位置
附近的代码。这个代码位置的定义和在 break 命令中定义的相同,可以是一个行号:
(gdb) list 100 #列出当前代码文件中第 100 行附近代码
(gdb) list tcpdump.c:450 #列出 tcpdump.c 文件中第 450 行附近代码
也可以是一个函数名:
(gdb) list main #列出当前代码文件中 main 函数附近代码
(gdb) list inet.c:pcap_lookupdev #列出 inet.c 代码文件中指定函数附近代码
list 命令还可以指定要显示代码的具体范围:
(gdb) list FIRST,LAST
list 命令默认只会打印出 10 行源代码,如果觉得不够,可以使用如下命令修改:
(gdb) set listsize COUNT
如果想查看这个参数当前被设置成多少,可以使用如下命令:
(gdb) show listsize
如果你想看程序中一共定义了哪些函数,可以使用下面的命
令:
(gdb) info functions
print 和ptype命令
print:命令不仅可以显示变量值,也可以显示进行一定运算的表达式计算结果值,
甚至可以显示一些函数的执行结果值
p va_nm=value :修改变量的值
p server.port=6400
p var_nm:输出变量值
p &server.port
ptype var_nm:输出变量类型
ptype server
ptype server.port
info thread:查看所有线程
(gdb) info thread
Id Target Id Frame
- 1 Thread 0xb7d86080 (LWP 16140) “redis-server” 0xb7fdac31 in __kernel_vsyscall ()
2 Thread 0xb77ffb40 (LWP 16141) “bio_close_file” 0xb7fdac31 in __kernel_vsyscall ()
3 Thread 0xb6ffeb40 (LWP 16142) “bio_aof_fsync” 0xb7fdac31 in __kernel_vsyscall ()
4 Thread 0xb67fdb40 (LWP 16143) “bio_lazy_free” 0xb7fdac31 in __kernel_vsyscall ()
5 Thread 0xb5ffcb40 (LWP 16144) “jemalloc_bg_thd” 0xb7fdac31 in __kernel_vsyscall ()
LWP后面跟的数字16140是对应的线程id
thread 2:线程切换2号
thread 2
gdb) info thread
Id Target Id Frame
1 Thread 0xb7d86080 (LWP 16140) “redis-server” 0xb7fdac31 in __kernel_vsyscall ()
- 2 Thread 0xb77ffb40 (LWP 16141) “bio_close_file” 0xb7fdac31 in __kernel_vsyscall ()
3 Thread 0xb6ffeb40 (LWP 16142) “bio_aof_fsync” 0xb7fdac31 in __kernel_vsyscall ()
4 Thread 0xb67fdb40 (LWP 16143) “bio_lazy_free” 0xb7fdac31 in __kernel_vsyscall ()
5 Thread 0xb5ffcb40 (LWP 16144) “jemalloc_bg_thd” 0xb7fdac31 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdac31 in __kernel_vsyscall ()
#1 0xb7f49a6c in pthread_cond_wait@@GLIBC_2.3.2 () at …/sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S:187
#2 0x080df35c in bioProcessBackgroundJobs (arg=0x0) at bio.c:190
#3 0xb7f44295 in start_thread (arg=0xb77ffb40) at pthread_create.c:333
#4 0xb7e6f0ae in clone () at …/sysdeps/unix/sysv/linux/i386/clone.S:114
(gdb) frame 3
#3 0xb7f44295 in start_thread (arg=0xb77ffb40) at pthread_create.c:333
333 pthread_create.c: No such file or directory.
info args:查看函数的参数值
(gdb) info args
arg = 0xb77ffb40
(gdb) thread 1
[Switching to thread 1 (Thread 0xb7d86080 (LWP 16140))]
#0 0xb7fdac31 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdac31 in __kernel_vsyscall ()
#1 0xb7e6f88a in epoll_wait () at …/sysdeps/unix/syscall-template.S:84
#2 0x0806eb8b in aeApiPoll (eventLoop=0xb7d7e380, tvp=0xbffff1d4) at ae_epoll.c:112
#3 0x0806f7bd in aeProcessEvents (eventLoop=0xb7d7e380, flags=27) at ae.c:447
#4 0x0806fa73 in aeMain (eventLoop=0xb7d7e380) at ae.c:539
#5 0x0807d6c9 in main (argc=1, argv=0xbffff324) at server.c:5175
(gdb) frame 2
#2 0x0806eb8b in aeApiPoll (eventLoop=0xb7d7e380, tvp=0xbffff1d4) at ae_epoll.c:112
112 retval = epoll_wait(state->epfd,state->events,eventLoop->setsize,
(gdb) print *eventLoop
$8 = {maxfd = 7, setsize = 10128, timeEventNextId = 1, lastTime = 1599716689, events = 0xb7d0b380, fired = 0xb7cf6d00,
timeEventHead = 0xb7fc20f0, stop = 0, apidata = 0xb7fd0df8, beforesleep = 0x8075165 ,
aftersleep = 0x8075350 , flags = 0}
(gdb) print *tvp
$9 = {tv_sec = 0, tv_usec = 100000}
next:命令用调试的术语叫“单步步过”(step over),即遇到函数调用直接跳过,不
进入函数体内部。
step 命令(简写为 s)就是“单步步入”(step into),顾名
思义,就是遇到函数调用,进入函数内部
return:命令的作用是结束执行当前函数并返回,如果当前函数还有剩余的代码未执行
完毕,也不会执行了
finish 命令会执行函数到正常退出该函数,还可以指定该函数的返回值
until: 命令(简写为 u)可以指定程序运行到某一行停下来,当然也可以break lineNo设置断点,后执行continue也
可以跳转到该行
jump location:location可以是行数和函数地址
jump 555
jump +10:当前代码后10行
jump *0x12345:跳转到该地址的代码处
jump 跳转到代码处,跳转区间的代码不会运行
disassemble 查看反汇编
set args:传参数,后面参数空格分隔,则参数需引号括起;清楚参数,则后面不需要带参数,
show args:查看参数是否生效
(gdb) set args “zhangsan” “999”
(gdb) show args
Argument list to give program being debugged when it is started is "“zhangsan” “999"”.
(gdb) set args
(gdb) show args
Argument list to give program being debugged when it is started is “”.
tbreak:添加临时断点,该断点被hit一次后,临时断点就会被删除
watch:用来监视一个变量或者一段内存,当这个变
量或者该内存处的值发生变化时, GDB 就会中断下来。被监视的某个变量或者某个内存
地址会产生一个 watch point(观察点)
-
整型变量
int i;
watch i -
指针变量
char *p;
watch p、watch *p -
查看数组或内存区间
char szBuff[100];
watch szBuff
注意:当设置的观察点是一个局部变量时,局部变量无效后,观察点也会失效。在
观察点失效时 GDB 可能会提示如下信息:
Watchpoint 2 deleted because the program has left the block in which its expression is
valid.
info watch :查看watch断点
delete 断点编号:删除watch断点
display: 命令监视的变量或者内存地址
//多线程调试的话,由于cpu时间片分配给其他线程
可能出现在A线程调试时,会出现其他无法期望的结果
原因就是cpu时间片分配给B了
线程A调试时,先锁住
set scheduler-locking on
结束后释放锁
set scheduler-locking off
条件断点
break lineNo [condtion]:当条件满足时,程序执行到此暂停
//多进程调试
set follow-fork parent
show follow-fork mode查看当前进程是父进程还是子进程
set follow-fork child