松垮垮 松垮垮
首页
  • GPU并行编程
  • 图形学
  • 归并算法
  • 计算机视觉
  • css
  • html
  • JavaScript
  • vue
  • 压缩命令
  • cmdline
  • Docker
  • ftrace跟踪技术
  • gcov代码覆盖率测试
  • GDB
  • git
  • kgdb
  • linux操作
  • markdown
  • systemtap
  • valgrind
  • 设计模式
  • 分布式
  • 操作系统
  • 数据库
  • 服务器
  • 网络
  • C++
  • c语言
  • go
  • JSON
  • Makefile
  • matlab
  • OpenGL
  • python
  • shell
  • 正则表达式
  • 汇编
  • GPU并行编程
  • mysql
  • nginx
  • redis
  • 网络
  • 计算机视觉
  • 进程管理
  • linux调试
  • 【Python】:re.error bad escape i at position 4
  • 搭建ai知识助手
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

松垮垮

c++后端开发工程师
首页
  • GPU并行编程
  • 图形学
  • 归并算法
  • 计算机视觉
  • css
  • html
  • JavaScript
  • vue
  • 压缩命令
  • cmdline
  • Docker
  • ftrace跟踪技术
  • gcov代码覆盖率测试
  • GDB
  • git
  • kgdb
  • linux操作
  • markdown
  • systemtap
  • valgrind
  • 设计模式
  • 分布式
  • 操作系统
  • 数据库
  • 服务器
  • 网络
  • C++
  • c语言
  • go
  • JSON
  • Makefile
  • matlab
  • OpenGL
  • python
  • shell
  • 正则表达式
  • 汇编
  • GPU并行编程
  • mysql
  • nginx
  • redis
  • 网络
  • 计算机视觉
  • 进程管理
  • linux调试
  • 【Python】:re.error bad escape i at position 4
  • 搭建ai知识助手
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 压缩命令
  • cmdline
  • Docker
  • ftrace跟踪技术
  • gcov代码覆盖率测试
  • GDB
    • gdb的启动
    • 退出gdb quit(q)
    • 查看源代码list(l)
    • 运行程序 run(r)
      • 运行环境
      • 工作目录
      • 运行shell程序
      • 程序的输入输出
      • 调试已运行的程序
    • 单步/断点调试
      • 恢复程序运行到下个断点
      • 单步跟踪
      • 多步跟踪
      • 查看当前变量
      • 自动显示
      • 历史记录
    • 暂停 / 恢复程序运行
      • 设置断点 break(b)
      • 设置观察点 watch
      • 设置捕捉点(CatchPoint)
    • 维护停止点
      • 清除停止点
      • 暂停停止点
      • 维护停止条件
      • 条件断点
    • 运行的程序在被停止住时,运行一些命令
    • 信号
    • 多进程
      • 方法一
      • 方法二
    • 线程
      • 线程查看死锁
    • 显示源代码
    • 编辑文件edit
    • 源代码的内存查看
      • 查看内存地址的值
      • 修改内存的值
    • 内存泄漏检测
    • new失败
  • git
  • kgdb
  • linux操作
  • markdown
  • systemtap
  • valgrind
  • 设计模式

  • 工具和开发
songkuakua
2025-02-15
目录

GDB

# GDB

Owner: -QVQ-

set detach-on-fork off

set follow-fork-mode child

set scheduler-locking

在gcc时加上-g启用gdb调试gcc -g hello.c -o hello

如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址

gdb —help例出gdb的命令种类,要看种类中的命令,可以使用 help 命令,如:help breakpoints

gdb中,输入命令时,只用打命令的前几个字符就可以了,当然可以敲击两次TAB键来补齐命令的全称

info sources 命令默认只显示源文件的信息(.c、.h、.cpp等),但是你可以通过 set substitute-path 命令来设置路径映射,让 GDB 能够显示编译后的文件(.o 文件)的信息。例如,如果你的源代码文件在 /home/user/project/src 目录下,编译后的文件在 /home/user/project/build 目录下,则可以使用以下命令:

set substitute-path /home/user/project/src /home/user/project/build

1
2

这将把源代码目录 /home/user/project/src 映射到编译后的目录 /home/user/project/build,这样 GDB 就能够正确地显示编译后的文件的信息了。

如果你想查看更多的文件信息,可以使用 info files 命令。这个命令会显示编译后的所有文件的信息,包括编译选项、符号表、调试信息等等。

# 基础

# gdb的启动

  • gdb 目标程序

  • gdb program core

    同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件

  • gdb attach 1234

    如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID,program应该在PATH环境变量中搜索得到。

    gdb -p 1234

GDB的启动开关

  • -symbols=SYMFILE 从指定文件中读取符号表。
  • -se=FILE 从指定文件中读取符号表信息,并把他用在可执行文件中。
  • -core=COREFILE 调试时core dump的core文件。
  • -directory=DIR 加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。

# 退出gdb quit(q)

要退出gdb时,只用发quit或命令简称q就行了。

# 查看源代码list(l)

info sources 查看所有文件

info source 文件 查看指定文件,支持通配符

file 文件

# 运行程序 run(r)

set args 参数可指定运行时参数。(如:set args10 20 30 40 50)

show args 命令可以查看设置好的运行参数。

# 运行环境

path 路径 可设定程序的运行路径。

show paths 查看程序的运行路径。

set env *environmentVarname=value* 设置环境变量。如:set env *USER=benben*

show env *[varname]* 查看环境变量,不带varname,打印出当前所有环境变量。

# 工作目录

cd 相当于shell的cd命令。

pwd 显示当前的所在目录。

# 运行shell程序

shell 程序

make重新构建程序,等价shell make

# 程序的输入输出

info terminal 显示你程序用到的终端的模式。

使用重定向控制程序输出。如:run > outfile

tty命令可以设置输入输出使用的终端设备。如:tty /dev/tty1

# 调试已运行的程序

  1. gdb外用,ps查看正在运行的程序的PID(进程ID),gdb PID *process-id* 格式挂接正在运行的程序。
  2. gdb内用,先用gdb 关联上源代码,并进行gdb,在gdb中用attach *process-id* 命令来挂接进程的PID。并用detach来取消挂接的进程。

# 单步/断点调试

# 恢复程序运行到下个断点

continue *[ignore-count]*

c *[ignore-count]*

fg *[ignore-count]*

三个命令等价,ignore-count表示忽略其后的断点次数

# 单步跟踪

step(s) *[count]* 如果有函数调用,他会进入该函数,count表示跟踪几步

next(n) *[count]* 如果有函数调用,不会进入该函数

set step-mode on/off 打开/关闭step-mode模式,于是,在进行单步跟踪时,程序会因为没有debug信息而停住。这个参数有很利于查看机器码。

show step-mode 查看当前step-mode模式状态

# 多步跟踪

finish 运行到当前函数返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。

until(u) 跳出循环体

until(u) *location* 跳到指定位置,可以跳过递归

# 查看当前变量

p(display) 变量名

info locals 打印出当前函数中所有局部变量和值

info catch 打印出当前函数的异常处理信息

可以通过prinf /f 变量名 打印出变量的值,/f表示输出的格式,

为了支持变量的查看编译指令应当为

g++ -g -O0 文件名 -o 输出 -std=c++11 -lpthread

使用c11,使用c++自带的线程库

这里的输出支持表达式:

print array[0]@2 输出数组0-2的值

::指定文件或函数中的变量

{type} addr 表示一个指向内存地址的类型为type的一个对象。

p port=6400 # 修改变量值
p /s server # 以指定类型输出
ptype server # 输出指定变量的类型
1
2
3

finish跳出当前函数

return 指定值结束执行当前函数

# 自动显示

display *expr*

设定好了变量后,当程序停下来时能一直显示变量的值,即使没有变动

undisplay *dnums* 删除自动显示的编号(2-5可以是范围)

disable display *dnums...* 取消

enable display *dnums...* 启用

info display 查看display设置的自动显示的信息

# 历史记录

每查看一次变量的值都会被记录下来变量的编号

通过show values [+n] 显示历史变量值的变化

# 暂停 / 恢复程序运行

info program 来查看程序的是否在运行,进程号,被暂停的原因。

在gdb中,我们可以有以下几种暂停方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程停止(Thread Stops)。如果要恢复程序运行,可以使用continue(c)命令。

# 设置断点 break(b)

可用通过tab来补齐函数名称

(gdb) b make_ <按TAB键>

tb:临时添加一个断点

break *function* 进入函数的时候停住 break *linenum*在指定行号停住。

break *+offset*

break -*offset*在当前行号的前面或后面的offset行停住。offset为自然数。

break *filename:function* 在源文件filename的function函数的入口处停住。

break *address 在程序运行的内存地址处停住。

break命令没有参数时,表示在下一条指令处停住。

break ... if *cond* ...可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。

注意对于如下语句

1 for(int i = 0; i < 10; i++) //break 1 if i > 4 这样的断点是无效的
2      cout<<"i"<<endl;       //break 2 if i > 4 这样才行
3 return 0
1
2
3

查看断点:

info breakpoints(break) *n*命令查看断点,n表示第几个断点

断点菜单:

break function(type) 指定参数类型对应的那个重载函数

实测中如果不加参数会把所有同名函数都打上断点

(gdb) b String::after//这个函数有多个重载,gdb会给出重载的所有函数的菜单
[0] cancel
[1] all
[2] file:String.cc; line number:867
[3] file:String.cc; line number:860
[4] file:String.cc; line number:875
[5] file:String.cc; line number:853
[6] file:String.cc; line number:846
[7] file:String.cc; line number:735
> 2 4 6//选择需要的函数打断点
Breakpoint 1 at 0xb26c: file String.cc, line 867.
Breakpoint 2 at 0xb344: file String.cc, line 875.
Breakpoint 3 at 0xafcc: file String.cc, line 846.
Multiple breakpoints were set.
Use the "delete" command to delete unwanted breakpoints.
(gdb)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

可见,GDB列出了所有after的重载函数,你可以选一下列表编号就行了。0表示放弃设置断点,1表示所有函数都设置断点。

# 设置观察点 watch

(程序运行时可用)

watch *expr*为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。

rwatch *expr 当表达式(变量)expr被读时,停住程序。*

awatch *expr* 当表达式(变量)的值被读或被写时,停住程序。

info watchpoints 查看观察点

# 设置捕捉点(CatchPoint)

catch *event* 当event发生时,停住程序。

event为以下内容:

1、throw 一个C++抛出的异常。(throw为关键字)

2、catch 一个C++捕捉到的异常。(catch为关键字)

3、exec 调用系统调用exec时。(exec为关键字,目前此功能只在HP-UX下有用)

4、fork 调用系统调用fork时。(fork为关键字,目前此功能只在HP-UX下有用)

5、vfork 调用系统调用vfork时。(vfork为关键字,目前此功能只在HP-UX下有用)

6、load 或 load 载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)

7、unload 或 unload 卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)

tcatch *event* 只设置一次捕捉点,当程序停住以后,应点被自动删除。

# 维护停止点

# 清除停止点

clear **(程序运行时)**清除所有的已定义的停止点。

clear *function* 清除所有设置在函数上的停止点。

clear *linenum*清除所有设置在指定行上的停止点。

clear *filename:linenum* 清除所有设置在指定文件:指定行上的停止点。

delete(d) *[breakpoints] [range...]*删除指定的断点,breakpoints可有可无。。range 表示断点号的范围(如:3-7)(不指定,则删除所有断点)。更建议用disable

# 暂停停止点

disable(dis) *[breakpoints] [range...]暂停这个*停止点(当你还需要时,enable即可),breakpoints为停止点号。(不指定,disable所有的停止点)。

enable *[breakpoints] [range...] 恢复*所指定的停止点,breakpoints可没有。

enable *[breakpoints] once range...启用*所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable。

enable *[breakpoints] delete range...启用*所指定的停止点,当程序停止后,该停止点马上被GDB自动删除。

# 维护停止条件

对于break ... if *cond*和watch ... if *cond* 这样的语句,可以用condition命令来修改cond条件

condition [*bnum] [expression]* 修改断点号为bnum的停止条件为expression。

condition *bnum* 清除断点号为bnum的停止条件。忽略断点号为bnum的停止条件count次。

ignore *bnum count*

# 条件断点

break example.c:10 if counter == 100
1

# 运行的程序在被停止住时,运行一些命令

commands [bnum]//bnum为断点号
... command-list ...
end
1
2
3
break foo if x>0

commands
printf "x is %d ",x//这里可以运行所有gdb的命令
continue
end
1
2
3
4
5
6

清楚断点命令,就是执行commands,再end

调用函数:

call helperFunction()
1

# 信号

信号是一种软中断,是一种处理异步事件的方法

  • handle signal *[keywords...]*

在GDB定义一个信号处理,定义一个要处理信号的范围(如:SIGIO-SIGKILL,其中包括SIGIO,SIGIOT,SIGKILL三个信号),也可以使用关键字all 表示处理所有信号。

信号:

SIGINT表示中断字符信号

SIGBUS表示硬件故障的信号;

SIGCHLD表示子进程状态改变信号;//指新建和离开

SIGKILL表示终止程序运行的信号

[keywords...]:

nostop:当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号

stop:当被调试的程序收到信号时,GDB会停住你的程序

print:当被调试的程序收到信号时,GDB会显示出一条信息

noprint:当被调试的程序收到信号时,GDB不会告诉你收到信号的信息

info signals/info handle 查看哪些信号在被GDB检测中

signal SIGINT 当程序收到ctrl+c终止时,使其继续运行下去,调试收到信号后的中断处理

# 多进程

# 方法一

调试子进程还是父进程 show follow-fork-mode # 展示模式 set follow-fork-mode parent # 调试父进程(默认) set follow-fork-mode child # 调试子进程

单进程调试还是多进程调试: show detach-on-fork # 展示模式 set detach-on-fork on # 单进程调试(默认) set detach-on-fork off # 多进程调试

查看进程信息: info inferiors

切换进程:

inferior 1

开启了子进程调试或者多进程调试后,当创建进程时,会触发断点

# 方法二

attach依附每个进程单独调试,但是对于运行的进程没有办法gdb上去,因此,需要编程时让运行的进程先暂停,gdb依附上后,修改对应变量使得其继续运行

# 线程

可以定义断点是否在所有线程还是在某个特定的线程上

  • break *linespec* thread *threadno*

linespec指定了断点设置在的源程序的行号

threadno指定了线程的ID ,不指定则表示所有线程信息

(注意这个ID是GDB分配的,info threads 查看正在运行程序中的线程信息)

可以多次info threads查看线程是否在lock_wait状态,

break frik.c:13 thread 28 if bartab > lim

主程序在单步调试时,线程也会恢复运行

  • thread 线程号 进入具体线程
  • bt(backtrace) n

能打印当前的函数调用栈的所有信息,n表示打印前n行,-n表示打印倒数n层

上面是栈顶,下面是栈地,即高地址是栈底,低地址是栈顶

  • up *n* 表示向栈的上面移动n层,可以不打n,表示向上移动一层。
  • down *n* 表示向栈的下面移动n层,可以不打n,表示向下移动一层。
  • frame *n* n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

上面三个命令会移动层数并打印值,如果不想打印值

  • select-frame 对应于 frame 命令。

  • up-silently *n* 对应于 up 命令。

  • down-silently *n* 对应于 down 命令。

  • frame(f)查看当前栈层

打印出这层的信息:栈的层编号、当前的函数名、函数参数值、函数所在文件及行号,函数执行到的语句

  • info frame(f) 打印出当前栈层更详细的信息:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。

指定线程调试

  • show scheduler-locking,查看设置
  • set scheduler-locking <on><off><step>
    • on,表示调试线程执行时,其余线程锁定,阻塞等待,
    • off ,表示不锁定其他线程
    • step ,表示在step(单步)调试时,只有当前线程运行

使用 info threads 命令查看当前正在运行的线程,找到指定线程的 ID。然后使用 thread <ID> 命令进入该线程。最后使用 where 或 bt 命令查看该线程的调用栈,从中可以看到该线程的调用关系,即被哪个函数创建。

示例:

(gdb) info threads
  3 Thread 0x7ffff5f4c700 (LWP 4846)  0x00007ffff79f0f3d in __GI___poll (fds=0x562d879ec830, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
  2 Thread 0x7ffff674d700 (LWP 4845)  0x00007ffff79f0f3d in __GI___poll (fds=0x7ffff674c3a0, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
* 1 Thread 0x7ffff7fcb700 (LWP 4843)  0x0000000000401c09 in main ()
(gdb) thread 3
[Switching to thread 3 (Thread 0x7ffff5f4c700 (LWP 4846))]
#0  0x00007ffff79f0f3d in __GI___poll (fds=0x562d879ec830, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
29	../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
(gdb) where
#0  0x00007ffff79f0f3d in __GI___poll (fds=0x562d879ec830, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x0000562d877f07d8 in ?? ()
#2  0x0000562d877f07a8 in ?? ()
#3  0x00007ffff6c8f6db in start_thread (arg=<optimized out>) at pthread_create.c:463
#4  0x00007ffff7a51a3f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

在上面的示例中,我们先使用 info threads 查看所有线程的信息,然后找到 ID 为 3 的线程,使用 thread 3 命令进入该线程,最后使用 where 查看该线程的调用栈,从中可以看到该线程是在 start_thread 函数中创建的。

# 线程查看死锁

首先可以查看该进程CPU利用率,内存利用率的情况,死锁让线程处于阻塞,基本不占有CPU

查看指定进程情况ps aux | grep 程序名

top -Hp pid

法一:

  1. attach id关联到发生死锁的进程id
  2. info threads查看当前进程中所有线程的信息,也可以查看到部分堆栈信息
  3. thread id进入具体线程
  4. bt查看当前线程堆栈信息,查看上锁和等待锁的情况
  5. 重复第3、4步,确定哪几个线程及哪几把锁发生的死锁,

法二:

对于c++11的std::mutex

source -v [deadlock.py](http://deadlock.py/)

deadlock

自动检测是否有死锁,并指明具体的线程

# 显示源代码

  • list *linenum* 打印出当前行号上下文的内容
  • list 函数名 打印出函数名附近的内容
  • list 显示当前行后面的源码
  • list - 显示当前行前面的源程序
  • list *first,last* 显示first到last行的内容

在list加上+/-表示偏移多少行

搜索文件:

search <regexp>从当前行的开始向下搜索

reverse-search <regexp> 从当前行开始向上搜索

regexp是正则表达式,做字符串匹配

原理就是检测线程之间是否存在环

# 编辑文件edit

进入GDB调试前,export EDITOR=/usr/bin/vim 命令指定文本编辑器

edit 16 //表示激活文件中的第16 行的代码

edit func //表示激活文件中的 func 处的代码,也可以加上文件名

edit test.c : 16 //表示激活 test.c 文件的第16 行

这种修改是临时的,退出后不会保存

# 源代码的内存查看

info line n 查看n行代码的在内存的位置

后面可跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”

disassemble 查看源程序的当前执行时的汇编语言

后面同样可跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”

# 查看内存地址的值

info registers 查看寄存器的值

格式:x/<n/f/u> <addr>

n:是正整数,表示需要显示的内存单元的个数,即从当前地址向后显示n个内存单元的内容,一个内存单元的大小由第三个参数u定义。

f:表示addr指向的内存内容的输出格式,s对应输出字符串,此处需特别注意输出整型数据的格式:

x 按十六进制格式显示变量。

d 按十进制格式显示变量。

u 按十六进制格式显示无符号整型。

o 按八进制格式显示变量。

t 按二进制格式显示变量。

a 按十六进制格式显示变量。

c 按字符格式显示变量。

f 按浮点数格式显示变量。

u:就是指以多少个字节作为一个内存单元-unit,默认为4。当然u还可以用被一些字符表示,如b=1 byte, h=2 bytes,w=4 bytes,g=8 bytes. <addr>:表示内存地址。

# 修改内存的值

set {<格式>} <地址> = <值>

# set {<格式>} <地址> = <值>
set {int}0x1000 = 0x55

# set $<寄存器名> = <值>
set $eax = 100
1
2
3
4
5

# 使用

# 内存泄漏检测

ASan检测器

在gcc时加入-fsanitize=address

运行时可以报出内存泄漏地址、堆溢出、栈溢出、全局内存溢出、内存释放后的继续使用

# new失败

To break out of a loop in GDB, you can use the interrupt command, which sends a SIGINT signal to the program being debugged. This will cause the program to stop executing and return control to GDB. Once you have interrupted the program, you can use GDB commands to examine its state and debug any issues.

disass 函数名 生成目标函数的汇编代码

gdb调试的layout使用_gdb layout_zhangjs0322的博客-CSDN博客 (opens new window)

To break out of a loop in GDB, you can use the interrupt command, which sends a SIGINT signal to the program being debugged. This will cause the program to stop executing and return control to GDB. Once you have interrupted the program, you can use GDB commands to examine its state and debug any issues.

# gdb汇编级调试

set disassemble-next-line on

使其能打印出下一条要执行的汇编代码

si单步调试(step into)

ni单句调试(step over)

在使用GDB进行汇编级调试时,输出结果的每一列代表以下含义:

  • 指令地址:当前正在执行的指令的内存地址。
  • 指令字节:当前指令组成的字节的十六进制表示。
  • 汇编代码:当前指令的人类可读的汇编代码。
  • 注释:此列可能包含有关当前指令的其他信息,例如源代码行号或寄存器值。

追踪寄存器的值 info registers <register-name>。

display /x $<register-name> 以十六进制格式显示寄存器的值,每次GDB停止程序时都会显示该值。

disassemble查看当前正在执行的函数的汇编代码

layout asm 命令。显示源代码、反汇编和寄存器值。

您可以使用 layout next 命令在不同的显示模式之间切换。

jump*汇编地址 命令跳转到指定的汇编语句

_ZN6netbox7RPCPool18UseInjectionFaultsEiRKNS_8EndpointE+80 是一个C++的符号名。它代表了 netbox::RPCPool 类的成员函数 UseInjectionFaults,该函数接受一个整数和一个对 netbox::Endpoint 类的常量引用作为参数,并返回从函数开始位置偏移80个字节的内存位置的值。结尾的 +80 表示从函数开始位置到返回值位置的偏移量。

上次更新: 2025/02/21, 14:57:10
gcov代码覆盖率测试
git

← gcov代码覆盖率测试 git→

最近更新
01
搭建ai知识助手
02-23
02
边缘检测
02-15
03
css
02-15
更多文章>
Theme by Vdoing | Copyright © 2025-2025 松垮垮 | MIT License | 蜀ICP备2025120453号 | 川公网安备51011202000997号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 纯净模式