Linux调试器-gdb使用

news2024/12/22 23:59:47

目录

1. 背景

2. 开始使用

3. 理解

创建需要调试的代码

debug&&release

4 详细调试

 list/l 行号

list/l 函数名

r或run

break(b)

info b(reak)

d num

disable breakpoints

enable breakpoints

n (next)

s(step)

breaktrace(或bt)

p 变量

display 变量名

undisplay

until X行号

 finish

 c


调试器:核心工作,主要是为了定位问题
所有查看的指令不影响实际的调试指令

1. 背景

程序的发布方式有两种,debug模式和release模式
Linux gcc/g++出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项

2. 开始使用

  • gdb binFile 退出: ctrl + d 或 quit 调试命令:
  • list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
  • list/l 函数名:列出某个函数的源代码。
  • r或run:运行程序。
  • n 或 next:单条执行。
  • s或step:进入函数调用
  • break(b) 行号:在某一行设置断点
  • break 函数名:在某个函数开头设置断点
  • info break :查看断点信息。
  • finish:执行到当前函数返回,然后挺下来等待命令
  • print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数

  • p 变量:打印变量值。
  • set var:修改变量的值
  • continue(或c):从当前位置开始连续而非单步执行程序
  • run(或r):从开始连续而非单步执行程序
  • delete breakpoints:删除所有断点
  • delete breakpoints n:删除序号为n的断点
  • disable breakpoints:禁用断点
  • enable breakpoints:启用断点
  • info(或i) breakpoints:参看当前设置了哪些断点
  • display 变量名:跟踪查看一个变量,每次停下来都显示它的值
  • undisplay:取消对先前设置的那些变量的跟踪
  • until X行号:跳至X行
  • breaktrace(或bt):查看各级函数调用及参数
  • info(i) locals:查看当前栈帧局部变量的值
  • quit:退出gdb

3. 理解

创建需要调试的代码

[root@VM-12-17-centos lesson8]# mkdir gdb
[root@VM-12-17-centos lesson8]# cd gdb
[root@VM-12-17-centos gdb]# touch test.c
[root@VM-12-17-centos gdb]# ll
total 0
-rw-r--r-- 1 root root 0 Jan 17 19:39 test.c
[root@VM-12-17-centos gdb]# ls ../
gdb  Makefile  mytest  proc  test.c
[root@VM-12-17-centos gdb]# cp ../Makefile .
[root@VM-12-17-centos gdb]# ll
total 4
-rw-r--r-- 1 root root 71 Jan 17 19:40 Makefile
-rw-r--r-- 1 root root  0 Jan 17 19:39 test.c
[root@VM-12-17-centos gdb]# vim test.c
[root@VM-12-17-centos gdb]# cat test.c
#include <stdio.h>

int addToTop(int top)
{
  printf("enter addToTop\n");
  int i=1;
  int sum=0;
  for( i=1;i<=top;i++)
  {
    sum+=i;

  }
  printf("quit addToTop\n");
  return sum;
}


int main()
{
  int top=100;

  int result=addToTop(top);
  printf("result:%d\n",result);
  return 0;
}
[root@VM-12-17-centos gdb]# cat Makefile
mytest:test.c
	gcc -o mytest test.c -std=c99

.PHONY:clean
clean:
	rm -f mytest
[root@VM-12-17-centos gdb]# ll
total 8
-rw-r--r-- 1 root root  71 Jan 17 19:40 Makefile
-rw-r--r-- 1 root root 285 Jan 17 19:45 test.c

[root@VM-12-17-centos gdb]# vim Makefile
[root@VM-12-17-centos gdb]# make
gcc -o mytest test.c
test.c: In function ‘addToTop’:
test.c:8:3: error: ‘for’ loop initial declarations are only allowed in C99 mode
   for(int i=1;i<=top;i++)
   ^
test.c:8:3: note: use option -std=c99 or -std=gnu99 to compile your code
make: *** [mytest] Error 1

如果出现这种报错,该语法在C99标准下被支持,在Makefile内添加-std=c99

mytest:test.c
     gcc -o mytest test.c -std=c99                                                                      
                                          
   .PHONY:clean                           
   clean:
     rm -f mytest

debug&&release

 

 我们对之前生成的mytest重命名,使我们观察的现象更明显

[root@VM-12-17-centos gdb]# mv mytest mytest-release
[root@VM-12-17-centos gdb]# ll
total 20
-rw-r--r-- 1 root root   83 Jan 17 20:12 Makefile
-rwxr-xr-x 1 root root 8440 Jan 17 19:49 mytest-release
-rw-r--r-- 1 root root  292 Jan 17 19:49 test.c
[root@VM-12-17-centos gdb]# ./mytest-release
enter addToTop
quit addToTop
result:5050

我们生成debug方式编译的文件

[root@VM-12-17-centos gdb]# make
gcc -o mytest test.c -g -std=c99
[root@VM-12-17-centos gdb]# ll
total 32
-rw-r--r-- 1 root root   83 Jan 17 20:12 Makefile
-rwxr-xr-x 1 root root 9672 Jan 17 20:18 mytest
-rwxr-xr-x 1 root root 8440 Jan 17 19:49 mytest-release
-rw-r--r-- 1 root root  292 Jan 17 19:49 test.c
[root@VM-12-17-centos gdb]# mv mytest mytest-debug
[root@VM-12-17-centos gdb]# ll
total 32
-rw-r--r-- 1 root root   83 Jan 17 20:12 Makefile
-rwxr-xr-x 1 root root 9672 Jan 17 20:18 mytest-debug
-rwxr-xr-x 1 root root 8440 Jan 17 19:49 mytest-release
-rw-r--r-- 1 root root  292 Jan 17 19:49 test.c
[root@VM-12-17-centos gdb]# ./mytest-debug
enter addToTop
quit addToTop
result:5050

release、debug都能正常运行

debug版本内有很多的调试信息,其体积比release版本大

[root@VM-12-17-centos gdb]# readelf -S mytest-debug | grep -i debug
  [27] .debug_aranges    PROGBITS         0000000000000000  00001069
  [28] .debug_info       PROGBITS         0000000000000000  00001099
  [29] .debug_abbrev     PROGBITS         0000000000000000  00001191
  [30] .debug_line       PROGBITS         0000000000000000  0000121c
  [31] .debug_str        PROGBITS         0000000000000000  00001273
[root@VM-12-17-centos gdb]# readelf -S mytest-release | grep -i debug
[root@VM-12-17-centos gdb]# 

4 详细调试

 list/l 行号

显示binFile源代码,接着上次的位置往下列,每次列10行。

[root@VM-12-17-centos gdb]# gdb mytest-debug
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/lesson8/gdb/mytest-debug...done.
(gdb) l
11	
12	  }
13	  printf("quit addToTop\n");
14	  return sum;
15	}
16	
17	
18	int main()
19	{
20	  int top=100;
(gdb) l 0
1	#include <stdio.h>
2	
3	int addToTop(int top)
4	{
5	  printf("enter addToTop\n");
6	  int i=1;
7	  int sum=0;
8	  for( i=1;i<=top;i++)
9	  {
10	    sum+=i;
(gdb) l
11	
12	  }
13	  printf("quit addToTop\n");
14	  return sum;
15	}
16	
17	
18	int main()
19	{
20	  int top=100;
(gdb) l
21	
22	  int result=addToTop(top);
23	  printf("result:%d\n",result);
24	  return 0;
25	}
(gdb) l
Line number 26 out of range; test.c has 25 lines.
(gdb) 

list/l 函数名

列出某个函数的源代码,函数名居中
(gdb) l main
14	  return sum;
15	}
16	
17	
18	int main()
19	{
20	  int top=100;
21	
22	  int result=addToTop(top);
23	  printf("result:%d\n",result);

r或run

运行程序

(gdb) r
Starting program: /root/lesson8/gdb/mytest-debug 
enter addToTop
quit addToTop
result:5050
[Inferior 1 (process 480) exited normally]

break(b)

插入断点

(gdb) b 19
Breakpoint 1 at 0x4005d2: file test.c, line 19.

info b(reak)

查看断点信息

(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d2 in main at test.c:19
(gdb) r
Starting program: /root/lesson8/gdb/mytest-debug 

Breakpoint 1, main () at test.c:20
20	  int top=100;
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004005d2 in main at test.c:19
	breakpoint already hit 1 time

d num

删除断点(num是断点的序号)

(gdb) d 19
No breakpoint number 19.
(gdb) d 1
(gdb) info b
No breakpoints or watchpoints.
(gdb) b 19
Breakpoint 2 at 0x4005d2: file test.c, line 19.
(gdb) r
Starting program: /root/lesson8/gdb/mytest-debug 

Breakpoint 2, main () at test.c:20
20	  int top=100;
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x00000000004005d2 in main at test.c:19
	breakpoint already hit 1 time

        我们重新设置断点,然后发现当我们还未退出这一次gdb时,我们即便删除之前的断点,我们重新设置的断点的num会增加,这里提一个功能,就是打开/关闭断点,我们看到enb下是yes,说明该断点是打开的,尤其是当我们不确定代码哪里出现问题,我们设置多个但是不一定同时使用的断点时,num的递增计数方式及断点的打开/关闭结合的功能会很好地帮助我们解决问题。

disable breakpoints

禁用断点
(gdb) disable breakpoint 2
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep n   0x00000000004005d2 in main at test.c:19
	breakpoint already hit 1 time
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/lesson8/gdb/mytest-debug 
enter addToTop
quit addToTop
result:5050
[Inferior 1 (process 4066) exited normally]

enable breakpoints

启用断点
(gdb) enable breakpoint 3
(gdb) info b
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x00000000004005d2 in main at test.c:19

n (next)

逐过程

(gdb) r
Starting program: /root/lesson8/gdb/mytest-debug 

Breakpoint 1, main () at test.c:20
20	  int top=100;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
(gdb) n
22	  int result=addToTop(top);
(gdb) n
enter addToTop
quit addToTop
23	  printf("result:%d\n",result);
(gdb) l 22
17	
18	int main()
19	{
20	  int top=100;
21	
22	  int result=addToTop(top);
23	  printf("result:%d\n",result);
24	  return 0;
25	}
(gdb) 
Line number 26 out of range; test.c has 25 lines.
(gdb) n
result:5050
24	  return 0;
(gdb) n
25	}
(gdb) n
0x00007ffff7a2f555 in __libc_start_main () from /lib64/libc.so.6

s(step)

逐语句

(gdb) b 22
Breakpoint 2 at 0x4005d9: file test.c, line 22.
(gdb) d 1
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/lesson8/gdb/mytest-debug 

Breakpoint 2, main () at test.c:22
22	  int result=addToTop(top);
(gdb) s
addToTop (top=100) at test.c:5
5	  printf("enter addToTop\n");

调用函数实现压栈的过程,main函数在栈底,addToTop在其之上

 

 

 

breaktrace(或bt)

查看各级函数调用及参数

p 变量

打印变量值

(gdb) p sum
$1 = 3
(gdb) p i
$2 = 2
(gdb) p &sum
$3 = (int *) 0x7fffffffe438
(gdb) p &i
$4 = (int *) 0x7fffffffe43c

但是要一次一次地显示,非常麻烦

display 变量名

        常显示(内置类型,结构体等自定义类型,stl);

        跟踪查看一个变量,每次停下来都显示它的值

(gdb) display sum
1: sum = 3
(gdb) display i
2: i = 2
(gdb) display &sum
3: &sum = (int *) 0x7fffffffe438
(gdb) display &i
4: &i = (int *) 0x7fffffffe43c
(gdb) s
10	    sum+=i;
4: &i = (int *) 0x7fffffffe43c
3: &sum = (int *) 0x7fffffffe438
2: i = 3
1: sum = 3
(gdb) s
8	  for( i=1;i<=top;i++)
4: &i = (int *) 0x7fffffffe43c
3: &sum = (int *) 0x7fffffffe438
2: i = 3
1: sum = 6

undisplay

取消对先前设置的那些变量的跟踪

(gdb) s
8	  for( i=1;i<=top;i++)
4: &i = (int *) 0x7fffffffe43c
3: &sum = (int *) 0x7fffffffe438
2: i = 3
1: sum = 6
(gdb) undisplay &sum
warning: bad display number at or near '&sum'
(gdb) undisplay 3
(gdb) n
10	    sum+=i;
4: &i = (int *) 0x7fffffffe43c
2: i = 4
1: sum = 6

until X行号

跳至X行,执行完区间代码


(gdb) l 0
1	#include <stdio.h>
2	
3	int addToTop(int top)
4	{
5	  printf("enter addToTop\n");
6	  int i=1;
7	  int sum=0;
8	  for( i=1;i<=top;i++)
9	  {
10	    sum+=i;
(gdb) l
11	
12	  }
13	  printf("quit addToTop\n");
14	  return sum;
15	}
16	
17	
18	int main()
19	{
20	  int top=100;
(gdb) until 13
addToTop (top=100) at test.c:13
13	  printf("quit addToTop\n");
4: &i = (int *) 0x7fffffffe43c
2: i = 101
1: sum = 5050

 finish

执行到当前函数返回,然后停下来等待命令

(gdb) finish
Run till exit from #0  addToTop (top=100) at test.c:7
quit addToTop
0x00000000004005e3 in main () at test.c:22
22	  int result=addToTop(top);
Value returned is $5 = 5050
(gdb) n
23	  printf("result:%d\n",result);
(gdb) p result
$6 = 5050

c

从一个 断点处,直接运行至下一个断点处

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/lesson8/gdb/mytest-debug 

Breakpoint 3, main () at test.c:20
20	  int top=100;
(gdb) c
Continuing.

Breakpoint 2, main () at test.c:22
22	  int result=addToTop(top);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ConcurrentHashMap 的优化及其与HashTable, HashMap的区别

目录 1.优化一:减小锁粒度 2.优化二:只针对写操作加锁 3.优化三:CAS 4.优化四:扩容方式 HashMap是线程不安全的,HashTable是线程安全的,关键方法加锁了.我们更推荐的是ConcurrentHashMap ,更优化的线程安全哈希表 接下来我们总结一下ConcurrentHashMap 进行了哪些优化,比H…

Nessus 扫描log4J漏洞

系列文章 Nessus介绍与安装 Nessus Host Discovery Nessus 高级扫描 Nessus 扫描web服务 Nessus 扫描log4J漏洞 1.扫描环境搭建 1.centos7 安装装宝塔面板 2.面板里下载docker 3.进入centos检查docker是否生效 docker --version4.安装docker-compose Docker Compose是一个…

使用WordPress搭建知识库门户网站的优缺点

使用知识库软件进行知识管理&#xff0c;帮助企业节约成本&#xff0c;为客户提供一个自助服务平台&#xff0c;提高客户满意度&#xff0c;据调查&#xff0c;73%的客户宁愿在网上搜索答案&#xff0c;而不是给工作人员打电话或者发短信&#xff0c;搭建一个知识库可能会耗费时…

TCP如何保证可靠传输,为什么应用层还需要确认机制

TCP的可靠传输实现 以下区别&#xff1a; 1、可靠传输&#xff08;有序&#xff0c;保证对方一定接受到&#xff09; 2、流量控制 这两个功能都是依靠滑动窗口来实现的 TCP实现可靠传输依靠的有 序列号、自动重传、滑动窗口、确认应答等机制。 序列号 首先我们说下序列号&am…

文件操作相关知识

1、为什么使用文件 前面我们在实现通讯录时&#xff0c;每次运行结束后&#xff0c;我们所存储的数据都会消失。这是因为我们将数据存储在栈区、堆区等内存上&#xff0c;而内存是不具有持久性的&#xff0c;程序退出时&#xff0c;权限还给操作系统&#xff0c;这些数据就会丢…

Unity 3D PC平台发布|| Unity 3D Web 平台发布||Unity 3D Android平台发布

Unity 3D PC平台发布 PC 是最常见的游戏运行平台。 随着欧美游戏的崛起&#xff0c;PC 平台随之发生游戏登陆大潮。 在 PC 平台上发布游戏的步骤&#xff1a; 打开要发布的 Unity 3D 工程&#xff0c;执行 File → Build Settings 菜单命令。在 Platform 列表框中选择 PC&am…

Jenkins, docker-compose动态修改镜像版本升级部署

docker-compose镜像版本动态控制 提取.env文件进行配置通用环境变量 # 当前机器用户的home路径 HOST_HOME/home/guimu # 上传文件临时路径 TMP_DATA_PATH${HOST_HOME}/tempdata/ # media的home路径 MEDIA_HOME/media # 挂载的mysql的data路径 MYSQL_DATA_PATH${HOST_HOME}/my…

go 函数或者方法参数调用的过程

前言 最近做项目&#xff0c;使用go开发&#xff0c;但是在发生函数调用传参数时&#xff0c;对指针的指针的传递有难以理解的代码&#xff0c;就此分析过程。尤其是对于多重指针作为参数&#xff0c;而且对于一些内置函数的修改逻辑也需深入的理解。 1. demo package slice…

client-go源码学习(四):自定义Controller的工作原理、WorkQueue

本文基于Kubernetes v1.22.4版本进行源码学习&#xff0c;对应的client-go版本为v0.22.4 4、自定义Controller的工作原理 Controller中主要使用到Informer和WorkQueue两个核心组件 Controller可以有一个或多个Informer来跟踪某一个resource。Informer跟Kubernetes API Server保…

安装 Visual Studio Code、MinGW-w64、CMake

文章目录1.安装 Visual Studio Code1.1 下载1.2 安装2.安装 MinGW-w642.1 下载2.2 解压到合适的目录下2.3 添加到环境变量2.4 测试是否安装成功3.安装 CMake3.1 下载3.2 解压到合适的目录下3.3 添加到环境变量3.4 测试是否安装成功1.安装 Visual Studio Code 1.1 下载 Visual…

Options API

computed计算属性 1、复杂data的处理方式 我们知道&#xff0c;在模板中可以直接通过插值语法显示一些data中的数据。 但是在某些情况&#xff0c;我们可能需要对数据进行一些转化后再显示&#xff0c;或者需要将多个数据结合起来进行显示&#xff1b; 比如我们需要对多个d…

自动驾驶控制算法之车辆纵向控制(project)

本文为深蓝学院-自动驾驶控制与规划-第二章作业 目录 1 project introduction 2 思路提示 3 解决积分饱和的方法 3.1 IC 积分遇限削弱法 3.2 BC 反馈抑制抗饱和 4 ROSLGSVL联合仿真 1 project introduction 本项目希望大家根据PID控制方法实现一个巡航控制系统。我们已…

深度学习之边缘检测算法论文解读(EDTER: Edge Detection with Transformer)

引言 边缘检测是计算机视觉中最基本的问题之一&#xff0c;具有广泛的应用&#xff0c;例如图像分割[8&#xff0c;23&#xff0c;39&#xff0c;44&#xff0c;45&#xff0c;47]、对象检测[23]和视频对象分割[5&#xff0c;57&#xff0c;59]。给定输入图像&#xff0c;边缘…

webpack-dev-server:静态资源目录配置

目录 webpack-dev-server Webpack项目-配置自动打包 访问错误信息分析 简单配置静态资源访问目录 完整配置静态资源访问目录 directory属性 staticOptions属性 publicPath属性 serveIndex属性 watch属性 完整配置webpack.config.js示例 默认显示index.html内容配置 默…

fsdb DUMP的操作记录

参考链接&#xff1a; https://blog.csdn.net/ohuo666/article/details/124973939https://blog.csdn.net/ohuo666/article/details/124973939 https://blog.csdn.net/yuexiangallan/article/details/121760768https://blog.csdn.net/yuexiangallan/article/details/121760768…

基于 DolphinDB 的行情中心解决方案

随着国内量化金融的高速发展&#xff0c;行情数据所包含的微观交易结构信息越来越受到券商自营团队、资管团队以及各类基金的重视。这些交易团队迫切希望拥有一个与生产环境类似的投研仿真环境&#xff0c;提升研发的效率和质量。作为国内领先的高性能时序数据库厂商&#xff0…

【地铁上的Redis与C#】数据类型(七)--List类型

我们这篇文章开始讲解list类型。 什么是list list是一个存储空间保存多个数据&#xff0c;底层使用双向链表存储结构实现的一种Redis数据类型&#xff0c;。list类型一般用在存储多个数据&#xff0c;并需要对数据进入存储空间的顺序进行区分的情况下。list的存储方式是一个存…

气泡法检漏技术特点分析和新型压力衰减法测试技术

摘要&#xff1a;针对传统的气泡法检漏技术&#xff0c;本文详细介绍了气泡法的基本原理、气泡法中的两种标准方法——加压法和真空法以及对应的标准规范&#xff0c;并对这两种气泡法进行了对比分析。本文还对气泡法的技术特点进行了分析&#xff0c;指出了气泡法检漏技术的局…

使用ruoyi-vue控制数据权限

说在前面 啥是数据权限?例如校长可以看到全部学生的信息,系主任可以看到该院系的学生信息,老师可以看到本班的学生信息,学生自己只能查看自己的信息 对于ruoyi的角色,我们只能控制用户可以访问那些菜单以及接口,而不能控制接口返回的数据 假如有这样一个需求,不同用户上传各…

赛狐ERP | 亚马逊卖家FBA常见问题解析!

许多亚马逊卖家在使用亚马逊FBA时经常会遇到一些问题&#xff0c;如FBA如何收费、如何提升发货数量、物流方式问题等问题&#xff0c;这些问题是常见问题&#xff0c;也是亚马逊卖方们应该把握的问题。下面就来跟大家分享一些常见的亚马逊FBA相关问题。一、亚马逊FBA如何收费&a…