Linux C/C++编程十gdb调试

一、gdb的概述

gdb是GNU开源组织发布的一个强大的UNIX下的程序调试工具。

二、gdb的使用场景

  • 启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
  • 可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
  • 当程序被停住时,可以检查此时你的程序中所发生的事。
  • 动态的改变你程序的执行环境。

三、gdb调试的简单使用

举个例子:
用root权限的Terminal(或一般权限的Terminal)的vi编辑器编写一个C程序 test.c

#include <stdio.h>
int main()
{
  int a = 1;
  int b = a;
  printf("a = %d, b =%d\n", a, b);
  return 0;
}

编译测试程序test.c生成可执行程序test

gcc -g test.c -o test

其中,-o生成可执行程序,-g用于添加调试信息,便于gdb调试

启动gdb

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

lr@bad3b2d61b59:~$ gdb test
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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)
lr@bad3b2d61b59:~$ gdb -q test
Reading symbols from test...done.
(gdb)

程序运行的上下文

1)程序运行参数
set args + 参数:可指定运行时参数
show args:可以查看设置好的运行参数
run:启动程序

(gdb) set args 10 10
(gdb) show args
Argument list to give program being debugged when it is started is "10 10".
(gdb) run
Starting program: /home1/lr/test 10 10
a = 1, b = 1
[Inferior 1 (process 11817) exited normally]
(gdb)

2)工作目录
cd:相当于shell的cd命令
pwd:显示当前的所在目录

(gdb) cd
Working directory /home1/lr.
(gdb) pwd
Working directory /home1/lr.

调试代码

1)run:运行程序,可以简写为r

(gdb) run 10 10
Starting program: /home1/lr/test 10 10
a = 1, b = 1
[Inferior 1 (process 14528) exited normally]
(gdb)

2)start:启动,停留在 main 函数,分步调试

(gdb) start 10 10
Temporary breakpoint 1 at 0x40052e: file test.c, line 4.
Starting program: /home1/lr/test 10 10

Temporary breakpoint 1, main () at test.c:4
4         int a = 1;
(gdb)

3)next:单步跟踪,回车显示下一行代码,可简称n

(gdb) next
5         int b = a;
(gdb)
6         printf("a = %d, b = %d\n", a, b);
(gdb)
a = 1, b = 1
7         return 0;
(gdb)
8       }
(gdb)

4)step:单步跟踪,进入被调用的函数体内,可简称s

(gdb) step
6         printf("a = %d, b = %d\n", a, b);
(gdb)
__printf (format=0x4005e4 "a = %d, b = %d\n") at printf.c:28
28      printf.c: No such file or directory.
(gdb)

5)finish:退出进入的函数

(gdb) finish
Run till exit from #0  __printf (format=0x4005e4 "a = %d, b = %d\n") at printf.c:28
a = 1, b = 1
main () at test.c:7
7         return 0;
Value returned is $1 = 13
(gdb)

6)continue:继续运行程序,可简称c

(gdb) c
Continuing.
a = 1, b = 1
[Inferior 1 (process 61522) exited normally]
(gdb)

7)until:在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体,可简称u

设置断点

list(简写l):查看源程序代码,默认显示10行,按回车键继续看余下的
break(简写 b):b+行号:在某行设置断点;b+行号+条件:设置条件断点
info breakpoints :显示断点信息;info b 显示全部断点

Num:断点编号
Disp:断点执行一次之后是否有效。 keep:有效;dis:无效
Enb:当前断点是否有效 。y:有效;n:无效
Address:内存地址
What:位置

del d:删除断点d;del:删除全部断点
run:运行至下个断点

(gdb) l
1       #include <stdio.h>
2       int main()
3       {
4         int a = 1;
5         int b = a;
6         printf("a = %d, b = %d\n", a, b);
7         return 0;
8       }
(gdb) gdb 4
Undefined command: "gdb".  Try "help".
(gdb) b 4
Breakpoint 1 at 0x40052e: file test.c, line 4.
(gdb) b 6
Breakpoint 2 at 0x40053b: file test.c, line 6.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000040052e in main at test.c:4
2       breakpoint     keep y   0x000000000040053b in main at test.c:6
(gdb) del 1
(gdb) info b
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at test.c:6
(gdb) run
Starting program: /home1/lr/test

Breakpoint 2, main () at test.c:6
6         printf("a = %d, b = %d\n", a, b);
(gdb) b 7 if a == 2
Breakpoint 3 at 0x400552: file test.c, line 7.

查看运行时的数据

print(简写p)+变量、字符串、表达式等:打印运行时的数据
ptype+变量:变量类型
whatis+变量:变量类型

Starting program: /home1/lr/test

Breakpoint 2, main () at test.c:6
6         printf("a = %d, b = %d\n", a, b);
(gdb) p a
$1 = 1
(gdb) whatis a
type = int
(gdb) ptype a
type = int
(gdb)

自动显示

可以设置一些自动显示的变量,当程序停住时,或是在单步跟踪时,这些变量会自动显示。相关的GDB命令是display。
display 变量名:设置需要自动显示的信息
info display:查看display设置的自动显示的信息
undisplay num(info display时显示的编号)
delete display dnums… :删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔

(gdb) display a
1: a = 1
(gdb) n
a = 1, b = 1
7         return 0;
1: a = 1
(gdb) info display
Auto-display expressions now in effect:
Num Enb Expression
1:   y  a
(gdb) undisplay 1
(gdb) n
8       }
(gdb) delete display 1
No display number 1.

退出gdb

quit(简称q)

四、gdb的基本使用命令总结

运行命令

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

设置断点

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:清除所有断点

查看源码

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

打印表达式

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: 显示当前堆栈页的所有变量

查看运行信息

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

分割窗口

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

cgdb强大工具

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论

打赏作者

事后不诸葛

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值