gdb的简单实用介绍

gdb调试


0: gdb的功能 :

gdb通过ptrace()这个系统调用实现对一个运行的程序进行调试
(0-1):启动你的程序,可以按照你自定义的要求随心所欲的运行程序。

(0-2):可以让调试程序在你所指定的位置的断点处停止。

(0-3):当程序停止时,可以检查此时你的程序中所发生的事情。

(0-4):动态的改变你程序的执行环境。

(0-5):调试运行程序。


1:编译生成执行文件:(linux下)
gcc -g test.c -o testcpp  (C++下 g++ -g test.c -o testcpp)

2:gdb启动方式: 以下的testcpp为执行文件 
    (2-1):gdb testcpp_program
    (2-2): gdb testcpp_program  core, 使用bt查看调用栈,以及寄存器现场信息。
    (2-3): gdb testcpp_program <PID> , 这个常见的有 gdb attach pid;gdb -p pid;
    
3:gdb常用参数

(gdb) l :(字母l)从第一行开始列出源码。 

(gdb) break n :在第n行处设置断点

(gdb) break func:在函数func()的入口处设置断点

(gdb) info break: 查看断点信息

(gdb) r:运行程序,当遇到断点后,程序会在断点出停止运行,等待用户输入下一个gdb命令

(gdb) n:单步执行(不进入调用函数内部)

(gdb) c:继续运行

(gdb) p 变量名 :打印/查看变量。 p <para_name> = xx; 设置变量

(gdb) bt:查看函数堆栈

(gdb)f 栈行数:  查看栈帧

(gdb) s:单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数

(gdb) 回车: 重复上一条命令

(gdb)delete 断点号n:删除第n个断点 等价于clear n (这里的n是断点所在行数)

(gdb)set args:设置运行程序时的命令行参数,如:set args 33 55

(gdb)watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch a

(gdb)quit:简记为 q ,退出gdb

(gdb) gdb attch pid (此pid为正在运行的进程)

(gdb) detach (结束attch的pid, 之后再quit)

(gdb) b 文件名:行号 (断点打在某一行)

(gdb) info  threads(当前进程所有的线程信息,*所指向的为当前线程)

(gdb) handle SIGUSR1 noprint nostop; handle SIGUSR2 noprint nodtop; (信号屏蔽)

(gdb) gdb -p pid -tui (一边看源码一边gdb, gdb -p pid等价于gdb attach)

(gdb) finish (跳出当前进入的函数)

(gdb) thread [thread number] (跳转到指定的线程)

(gdb) frame <n> (选择第n层调用栈帧)

(gdb)  gdb跟踪一个正在运行的进程(注意这个是不设置端点的做法。设置断点的话,就需要 b 之后c)
(gdb) gdb  XXX | tee -a file  将gdb记录的东西显示定向到file文件中

(gdb) infro threads  查看当前进程的所有线程信息

(gdb) t 线程号  切换线程

(gdb) CTRL+X+A  查看代码

(gdb) thread apply all bt   查看所有线程堆栈

(gdb) thread apply ID! ID2 command   在线程ID1 ID2执行GDB命令command

(gdb) b xxxx thread thread_ID 在线程上打断点

(gdb) set scheduler-locking off|on|step 

off 不锁定任何线程。所有线程都执行,默认值

on 只有当前被调试程序线程会执行

step命令调试线程时,其他线程不会执行。用next命令调试线程,其他线程会执行

注意:使用完放开

(gdb) set print element 100   多打印

(gdb) b func_name if 变量==XXX (字符串类型需要使用[0]=='X' 来判断了)

(gdb) 条件变量 set A=XX

4: gdb 调试core文件
(4-1):输入ulimit -c 如果结果为0,说明当程序崩溃时,系统并不能生成core dump。
(4-2):使用ulimit -c unlimited命令,开启core dump功能,并且不限制生成core dump文件的大小。如果需要限制,加数字限制即可。ulimit - c 1024
(4-3):默认情况下,core dump生成的文件名为core,而且就在程序当前目录下。新的core会覆盖已存在的core。通过修改/proc/sys/kernel/core_uses_pid文件,可以将进程的pid作为作为扩展名,生成的core文件格式为core.xxx,其中xxx即为pid
(4-4):通过修改/proc/sys/kernel/core_pattern可以控制core文件保存位置和文件格式。例如:将所有的core文件生成到/corefile目录下,文件名的格式为core-命令名-pid-时间戳. echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

5: 参考博客GDB调试工具总结 - 简书


6: gdb查看内存地址

(1) 查看内存地址 examine (缩写 x)

x/<n/f/u> <addr>

其中输出格式包括:

x: 16进制  d: 10进制 o: 8进制

eg: 

x/10wx addr   查看10个字节按16进制输出

x/10i addr 查看该地址的10条指令

7: watch内存 以及 info register 查看寄存器 

watch expr : GDB在expr被程序写及其值改变时停止

rwatch expr:  GDB在expr被程序读时停止

watrch *(int*)addr : 查看一个地址内存是否有变化

i r: 查看当前栈的所有寄存器信息。

8: gdb常用的技巧

一般进程都有心跳机制,使用gdb需要先关闭心跳功能,避免进程长时间断住导致重启。

(1)define  循环打印线程栈

(gdb)define all_bt;

      set $start=1

      set $stop=2

      while $start <= $stop

       thread $start

        bt

        set $start=$start+1

        end

        end

(2)gdb脚本

gdb_all_bt.sh (在这个脚本里面写gdb命令)

eg: 实现打印进程pid的所有线程调用栈

#!/bin/bash

pid=$1

for i in $(ls /proc/${pid}/task)

do

        echo "dump thread $i"

        gdb -batch -ex "bt" -p $i

done

执行脚本sh gdb_all_bt.sh

9: gdb多线程调试

eg: 常用命令

bt

info thread

thread apply all bt

thread apply 1 2 bt (查看线程1 2 的调用栈)

t 1

t 2

b func1 thread 1  (断点只对线程1生效)

当不指定线程,那么每个线程运行时候只要执行到这个函数栈都会停下来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值