gdb调试c

本文详细介绍了GDB的使用方法,包括启动方式、环境设置、流程控制、断点管理、内存与栈帧操作、多线程与多进程调试、信号处理以及代码和内存查看。通过实例演示了如何设置断点、条件断点、脚本调试,并展示了如何利用GDB进行复杂程序的调试。此外,还提供了用于输出数组特定元素的GDB脚本示例。
摘要由CSDN通过智能技术生成

启动

gdb 程序名
gdb 程序名 core文件
gdb --pid pid
gdb 程序名 -x 脚本

运行及环境设置

set args    		   #设置运行参数 如nginx -c tem.conf -> set args -c tem.conf
set env [变量名] =#设置环境变量
unset env [变量名]      #取消环境变量
show env [变量名]       #显示环境变量

流程控制

run 参数    #如nginx -c tem.conf  run -c tem.conf  等价于前面的 set args
start 参数  #开始运行,但是会在main函数停止
attach pid #附加进程 等价于 gdb --pid pid

next(n)    #下一个条语句 步进
step(s)    #下一个条语句 步入
ni		   #下一条汇编语句 步进
si		   #下一条汇编语句 步入

finish     #退出当前函数

p 		   		#输出
printf fmt,...  #输出 与c函数类似  -> printf "%s","hello\n\n" 不输出转义

断点命令

break(b)
tbreak      #与break相似,只是设置一次断点
rbreak      正则表达式 #给一批满足条件的函数打上断点

info breakpoints  #查看断点信息

delete  断点号  #删除断点
disable 断点号  #失效
enable  断点号  #启用

condition   断点号 条件    #增加断点条件  (如: condition 2 sum==6)
condition   断点号         #删除断点条件
ignore      断点号 数目    #忽略断点n次

commands    断点号    #断点触发后执行语句
	语句
end

demo

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
    int sum = 0;

    int i = 0;

    for (i = 0;i < 10;i++) {
        sum += i;
    }

    printf("sum = %d\n",sum);

    return 0;
}

代码断点

break 行号
break 函数名(默认是main函数的文件)
break 文件名:函数名 (如:b ngx_array.c:ngx_array_create)
break 文件名:行号

条件断点

b 行号 if 条件 (如: b 11 if i==5)

内存断点

awatch #读写断点

watch #写断点

rwaich #读断点

三个命令的用法一致,以awatch举例

awatch 变量名(如:awatch sum) #不建议这么使用
awatch *地址(如:awatch *0x000aaaxasd) #表示读写这个地址对应的内存断下

多线程调试

info threads     #看所有线程信息
thread 线程id 	#切换到指定线程
break 行号信息 thread 线程号   #线程断点

多进程调试

set follow-fork-mode child|parent  #fork后,需要跟踪谁
show follow-fork-mode

info forks                         #显示所有进程信息
fork 进程id                         #切换到某个进程
detach-fork 进程id                  #不再跟踪某个进程
delete fork 进程id                  #kill某个进程并停止对它的跟踪

进程信息查看

信号

info signals       #列出所有信号的处理方式
handle 信号    方式  #改变当前处理某个信号的方式
    方式包括:
    nostop  #   当信号发生时不停止,只打印信号曾经发生过
    stop    #   停止并打印信号
    print   #   信号发生时打印
    noprint #   信号发生时不打印
    pass/noignore #应用程序看到这个信号
    nopass/ignore #应用程序忽略这个信号

栈帧

bt         #查看堆栈


frame(f) [帧号]      #不带参数时显示所有帧信息,带参数时切换到指定帧

info    frame       #显示当前帧信息
info    frame addr  #显示指定地址的帧信息
info    args        #显示帧的参数
info    locals      #显示局部变量信息
info    catch       #显示本帧异常信息

内存查看

x   /nfu    地址    #   查看内存
    n       重复n次
    f       显示格式,为print使用的格式 z 16进制
    u       每个单元的大小,为
        b       byte
        h       2 byte
        w       4 byte
        g       8 byte
        
常用: x/20gz  地址   x/20wz  地址


gef使用者
dq  地址   8
dd  地址   4
dw  地址   2
dc  地址   1

显示长度 l
如:
dq 0x000addsafds l20

代码查看

list(l) [行号|函数|文件:行号]         #显示指定位置的信息,无参数为当前位置
set listsize    n                  #修改每次显示的行数
show listsize

info line [函数名|行号]     	        #显示指定位置对应的机器码地址范围
disassemble [函数名 | 起始地址 结束地址]    #对指定范围进行反汇编
set disassembly-flavor att|intel   #指定汇编代码形式
show disassembly-flavor

#宏查看 gcc 编译添加  -gdwarf-2 -g3
info macro 宏名

脚本

gdb 默认加载脚本 ~/.gdbinit

其他要加载脚本可以 在~/.gdbinit里source其他脚本 或者 使用 gdb -x

#变量设置
set $val = 0

#函数定义
#define fun_test
语句
end

#函数参数 $arg0 $arg1..

#分支 (仅仅支持这种 没有elif else if)
if 条件

else

end

#循环
while 条件

end

demo

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{
    int arr[] = {1,2,3,4,5,6,7};


    return 0;
}

脚本案例:写一个调试函数输出arr数组的所有下标是2的倍数的值

define for_int
    set $count = 0
    while($count < $arg1)
        if $count%2 == 0
            p $arg0[$count]
        end
        set $count++
    end
end

把脚本写入一个文件gdb_test

#启动
gdb test -x gdb_test
b 7
r
l

int main(int argc,char *argv[])
{
 	int arr[] = {1,2,3,4,5,6,7};

	return 0;$pc
}

for_int arr 7
$1 = 0x1
$2 = 0x3
$3 = 0x5
$4 = 0x7
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值