linux下gdb调试方法与技巧整理「建议收藏」

linux下gdb调试方法与技巧整理「建议收藏」目录一、gdb简介二、gdb使用流程1、启动gdb2、查看源码3、运行程序4、设置断点5、单步执行6、查看变量7、退出gdb三、gdb基本使用命令1、运行命令2、设置断点3、查看源码4、打印表达式5、查看运行信息6、分割窗口7、cgdb强大工具四、总结一、gdb简介GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。对于一名Linux下…

大家好,又见面了,我是你们的朋友全栈君。

一、gdb简介

GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c++程序员,gdb是必不可少的工具;

二、gdb使用流程

这里用c程序做基本演示,c++程序也是一样的;

1、启动gdb

编译一个测试程序,-g表示可以调试,命令如下:

gcc -g test.c -o test

启动gdb,命令如下:

gdb test 
gdb -q test //表示不打印gdb版本信息,界面较为干净;

测试如下:

root@ubuntu:/home/eit/c_test# gdb test
GNU gdb (Ubuntu 7.7-0ubuntu3) 7.7
Copyright (C) 2014 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...done.
(gdb) q
root@ubuntu:/home/eit/c_test# gdb -q test
Reading symbols from test...done.
(gdb) 

到此gdb启动完成!

2、查看源码

list(简写 l): 查看源程序代码,默认显示10行,按回车键继续看余下的。
测试如下:

(gdb) list 
9	#define MAX_SIZE
10	
11	int main()
12	{
13	    int i,fd,size1 ,size2 ,len;
14	    char *buf = "helo!I'm liujiangyong ";
15	    char buf_r[15];
16	    len = strlen(buf);
17	    fd = open("/home/hello.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
18	    if (fd<0)
(gdb) 
19	        {
20	            perror("open :");
21	            exit(1);
22	        }
23	    else
24	        {
25	        printf("open file:hello.txt %d\n",fd);
26	        }
27	    size1 = write(fd,buf,len);
28	    if (fd<0)
(gdb) 
29	    {
30	        printf("writre erro;");
31	
32	    }
33	    else
34	    {
35	        printf("写入的长度:%d\n写入文本内容:%s\n",size1,buf);
36	
37	    }
38	    lseek(fd,0,SEEK_SET);
(gdb) 
39	    size2 = read(fd,buf_r,12);
40	    if (size2 <0)
41	    {
42	        printf("read  erro\n");
43	    }
44	    else
45	    {
46	        printf("读取长度:%d\n 文本内容是:%s\n",size2,buf_r);
47	    }
48	    close(fd);    
(gdb) 
49	
50	
51	}
(gdb) 
Line number 52 out of range; write.c has 51 lines.
(gdb) 

3、运行程序

run(简写 r) :运行程序直到遇到 结束或者遇到断点等待下一个命令;
测试如下:

(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/eit/c_test/test 
open file:hello.txt 3
写入的长度:22
写入文本内容:helo!I'm liujiangyong 
读取长度:12
 文本内容是:helo!I'm liu
[Inferior 1 (process 19987) exited normally]
(gdb) 

4、设置断点

break(简写 b) :格式 b 行号,在某行设置断点;
info breakpoints :显示断点信息
Num: 断点编号
Disp:断点执行一次之后是否有效 kep:有效 dis:无效
Enb: 当前断点是否有效 y:有效 n:无效
Address:内存地址
What:位置

(gdb) b 5
Breakpoint 3 at 0x400836: file write.c, line 5.
(gdb) b 26 
Breakpoint 4 at 0x4008a6: file write.c, line 26.
(gdb) b 30
Breakpoint 5 at 0x4008c6: file write.c, line 30.
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
3       breakpoint     keep y   0x0000000000400836 in main at write.c:5
4       breakpoint     keep y   0x00000000004008a6 in main at write.c:26
5       breakpoint     keep y   0x00000000004008c6 in main at write.c:30
(gdb) 

5、单步执行

使用 continue、step、next命令
测试如下:

(gdb) r
Starting program: /home/eit/c_test/test 

Breakpoint 3, main () at write.c:12
12	{
(gdb) n
14	    char *buf = "helo!I'm liujiangyong ";
(gdb) 
16	    len = strlen(buf);
(gdb) 
17	    fd = open("/home/hello.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
(gdb) s
open64 () at ../sysdeps/unix/syscall-template.S:81
81	../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) 
main () at write.c:18
18	    if (fd<0)
(gdb) 
25	        printf("open file:hello.txt %d\n",fd);
(gdb) 
__printf (format=0x400a26 "open file:hello.txt %d\n") at printf.c:28
28	printf.c: No such file or directory.
(gdb) c
Continuing.
open file:hello.txt 3

Breakpoint 4, main () at write.c:27
27	    size1 = write(fd,buf,len);
(gdb) 
Continuing.
写入的长度:22
写入文本内容:helo!I'm liujiangyong 
读取长度:12
 文本内容是:helo!I'm liu
[Inferior 1 (process 20737) exited normally]
(gdb) 

6、查看变量

使用print、whatis命令
测试如下:

main () at write.c:28
28	    if (fd<0)
(gdb) 
35	        printf("写入的长度:%d\n写入文本内容:%s\n",size1,buf);
(gdb) print fd
$10 = 3
(gdb) whatis fd
type = int
(gdb) 

7、退出gdb

用quit命令退出gdb:

(gdb) r
Starting program: /home/eit/c_test/test 
open file:hello.txt 3
写入的长度:22
写入文本内容:helo!I'm liujiangyong 
读取长度:12
 文本内容是:helo!I'm liu
[Inferior 1 (process 20815) exited normally]
(gdb) q
root@ubuntu:/home/eit/c_test# 

continue(简写 c): 继续执行程序,直到下一个断点或者结束;
next(简写 n ):单步执行程序,但是遇到函数时会直接跳过函数,不进入函数;
step(简写 s) :单步执行程序,但是遇到函数会进入函数;
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体;
until+行号: 运行至某行,不仅仅用来跳出循环;
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息;
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55);
quit:简记为 q ,退出gdb;

三、gdb基本使用命令

1、运行命令

run:简记为 r ,其作用是运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
continue (简写c ):继续执行,到下一个断点处(或运行结束)
next:(简写 n),单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。
step (简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
until:当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
until+行号: 运行至某行,不仅仅用来跳出循环
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
call 函数(参数):调用程序中可见的函数,并传递“参数”,如:call gdb_test(55)
quit:简记为 q ,退出gdb

2、设置断点

break n (简写b n):在第n行处设置断点
(可以带上代码路径和代码名称: b OAGUPDATE.cpp:578)
b fn1 if a>b:条件断点设置
break func(break缩写为b):在函数func()的入口处设置断点,如:break cb_button
delete 断点号n:删除第n个断点
disable 断点号n:暂停第n个断点
enable 断点号n:开启第n个断点
clear 行号n:清除第n行的断点
info b (info breakpoints) :显示当前程序的断点设置情况
delete breakpoints:清除所有断点:

3、查看源码

list :简记为 l ,其作用就是列出程序的源代码,默认每次显示10行。
list 行号:将显示当前文件以“行号”为中心的前后10行代码,如:list 12
list 函数名:将显示“函数名”所在函数的源代码,如:list main
list :不带参数,将接着上一次 list 命令的,输出下边的内容。

4、打印表达式

print 表达式:简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,比如当前正在调试C语言的程序,那么“表达式”可以是任何C语言的有效表达式,包括数字,变量甚至是函数调用。
print a:将显示整数 a 的值
print ++a:将把 a 中的值加1,并显示出来
print name:将显示字符串 name 的值
print gdb_test(22):将以整数22作为参数调用 gdb_test() 函数
print gdb_test(a):将以变量 a 作为参数调用 gdb_test() 函数
display 表达式:在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值。如: display a
watch 表达式:设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序。如: watch a
whatis :查询变量或函数
info function: 查询函数
扩展info locals: 显示当前堆栈页的所有变量

5、查看运行信息

where/bt :当前运行的堆栈列表;
bt backtrace 显示当前调用堆栈
up/down 改变堆栈显示的深度
set args 参数:指定运行时的参数
show args:查看设置好的参数
info program: 来查看程序的是否在运行,进程号,被暂停的原因。

6、分割窗口

layout:用于分割窗口,可以一边查看代码,一边测试:
layout src:显示源代码窗口
layout asm:显示反汇编窗口
layout regs:显示源代码/反汇编和CPU寄存器窗口
layout split:显示源代码和反汇编窗口
Ctrl + L:刷新窗口

7、cgdb强大工具

cgdb主要功能是在调试时进行代码的同步显示,这无疑增加了调试的方便性,提高了调试效率。界面类似vi,符合unix/linux下开发人员习惯;如果熟悉gdb和vi,几乎可以立即使用cgdb。

8、常用gdb调试命令汇总

在这里插入图片描述

四、总结

总的来说在Linux下开发程序gdb/cgdb是必须学会使用的,他的强大之处远不止于此,在程序的调试中用它会提高的我们的调试效率,当然gdb的功能与使用技巧还不止于此,多多探索,多多学习使用。

参考链接:https://blog.csdn.net/horotororensu/article/details/82256832

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141564.html原文链接:https://javaforall.net

(1)
上一篇 2022年5月25日 下午4:00
下一篇 2022年5月25日 下午4:20


相关推荐

  • python encode和decode的区别_encode和decode的区别

    python encode和decode的区别_encode和decode的区别字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode(‘gb2312’),表示将gb2312编码的字符串str1转换成unicode编码。e…

    2022年10月7日
    4
  • 自定义 View 之富有弹性的 NestedScrollView

    自定义 View 之富有弹性的 NestedScrollView博主声明 转载请在开头附加本文链接及作者信息 并标记为转载 本文由博主威威喵原创 请多支持与指教 本文首发于此博主 威威喵 博客主页 https blog csdn net smile running 首先简单的介绍一下 NestedScroll 这个控件 它是继承自 FrameLayout 的一个可以滚动视图的控件 其位置是在我们的 suppo

    2026年3月19日
    3
  • SpringBoot项目整合支付宝

    SpringBoot项目整合支付宝SpringBoot 项目整合支付宝进行支付在盈利性网站应用中 我们经常要用到支付 支付宝和微信作为日常使用量较多的支付方式 无疑是大多数人的选择 今天我们选择支付宝为例子来讲解一下怎么在 SpringBoot 中进行整合 先看一下整个项目的目录和整合后的效果 整个项目目录结构 项目整合效果 下面详细来完成此工程 1 登录支付宝进行申请 图中

    2026年3月17日
    1
  • kafka官方文档_kafka groupid

    kafka官方文档_kafka groupid介绍Kafka是一个分布式的、分区的、冗余的日志提交服务。它使用了独特的设计,提供了所有消息传递系统所具有的功能。我们先来看下几个消息传递系统的术语:Kafka维护消息类别的东西是主题(topic).

    2022年8月1日
    5
  • MFC进度条编程控制[通俗易懂]

    MFC进度条编程控制[通俗易懂]好文章转来转去图片也找不到了 最原版的链接也打不开了 比较遗憾\*****************************************************************************************************************************************************************

    2022年7月12日
    21
  • 【教程】2026年OpenClaw(Clawdbot)AI龙虾5分钟安装超简单流程

    【教程】2026年OpenClaw(Clawdbot)AI龙虾5分钟安装超简单流程

    2026年3月14日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号