👻内容专栏: Linux操作系统基础
🐨本文概括: gdb的相关背景与命令使用。
🐼本文作者: 阿四啊
🐸发布时间:2023.9.21
背景
Linux中的debug和release
1.在用vs编译器时,我们知道程序发布的方式有两种:debug
模式和release
模式,在debug模式下可以进行调试操作,在release模式下不可以进行调试操作。在linux当中,我们编译代码的时候默认是release
模式.
如何去证明是release版本的呢?
方法一:首先,在mycode.c中写入一段简单的C语言代码,在Makefile文件中写入依赖方法与依赖关系,后面直接make命令自动编译。
powershell
[Asi@localhost day02]$ touch mycode.c
[Asi@localhost day02]$ ls >Makefile
[Asi@localhost day02]$ ll
total 4
-rw-rw-r-- 1 Asi Asi 18 Sep 21 15:09 Makefile
-rw-rw-r-- 1 Asi Asi 0 Sep 21 15:09 mycode.c
[Asi@localhost day02]$ cat mycode.c
#include<stdio.h>
int AddToTop(int n)
{
int sum = 0;
int i = 1;
for(;i <= n;i++)
{
sum += i;
}
return sum;
}
int main()
{
int top = 100;
int result = 0;
result = AddToTop(top);
printf("result = %d\n",result);
return 0;
}
[Asi@localhost day02]$ cat Makefile
mybin: mycode.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f mybin
[Asi@localhost day02]$ make
gcc -o mybin mycode.c
[Asi@localhost day02]$ ./mybin
result = 5050
我们使用gdb --vesion
命令,查看gdb调试工具的版本。
注:默认情况下gdb是没有安装的,我们可以执行sudoyum install gdb
命令进行安装。
cpp
[Asi@localhost day02]$ gdb --version
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/>.
然后我们输入gdb + 可执行文件名称 进行调试
发现最后()
中显示"no debugging symbols found",意思是没有debug信息被发现,是调试不了的。
powershell
[Asi@localhost day02]$ gdb mybin
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 /home/Asi/study/day02/mybin...(no debugging symbols found)...done.
说明linux当中,程序默认是release
模式的。
如果想要以debug
模式运行,需要在源文件当中gcc编译添加编译选项-g
(表示以debug模式编译该程序),修改之后编译再运行。
最后发现,没有显示"(no debugging symbols found)",修改为了debug模式,可以进行调试
- 在debug发布的时候,一定给可执行程序添加了某些debug信息,所以
形成debug版本的可执行程序的大小
>形成release版本的可执行程序的大小
我们在Makefile中修改目标文件,分别修改两份,一份以"mybin-g"命名,编译时加上-g选项,表示debug版本的可执行程序,一份以"mybin-r"命名,不加上-g选项,表示release版本的可执行程序。
最后ll
命令查看,确实如此。
另外,还可以只用readelf
命令查看linux中形成的可执行程序格式(ELF格式)
我们明显观察到 mybin-g 文件中与mybin-r文件相比,确实多了一些debug调试字段。这也进一步说明了我们的编译代码默认模式是release模式。
所以,你想让自己的程序能够被调试,那么在编译时就必须添加上-g
选项,以debug方式发布。
使用
进入与退出
进入gdb调试工具:gdb + binfile(可执行文件)
退出gdb:ctrl + d
或 quit
命令
列出
list + 行号
:显示binfile文件源代码,接着上次的位置往下列,每次列出10行。list也可以用l
字母表示
我们可以使用 l 0
或者l 1
列出源代码第一行,然后按「回车」键...... 可以将所有代码显示出来。
运行程序
run
:表示运行程序,相当于vs当中的「F5」键,表示开始调试,遇到断点会停下来,没有断点相当于开始执行不调试。run也可以用r
字母表示
设置断点
break + 行号
:在某一行设置断点,beak也可简写为b,例如b 18
,在第18行打上断点,随后报出相应信息。
break + 函数名
:在某个函数开头设置断点。
如果有多个文件的话,可以指定文件名 + 冒号 + 函数名
查看断点
intfo break
:查看断点信息,Num
为断点编号,Type
为类型,What
表示断点设置在哪个位置。
⚠️注意:断点的编号是在一个调试会话中逐渐递增的,如果删除某一个断点,创建下一个断点后,那么这个断点的编号为上一个删除断点的后一个数字,删除断点不代表创建断点编号也会刷新,而是一直处于递增的状态。如果退出gdb调试,那么所有断点都会被清除!
删除断点
delete breakpoints
:删除所有断点。
delete n
:删除编号为n的断点,delete也可用d表示。
禁用断点
disable n
:禁用编号为n的断点。表示断点只是暂时禁用,但还是存在的。
禁用编号为1的断点之后,Enb
的值由y变成了n
将编号为2的断点禁用之后,我们使用r
命令,此时程序直接就跑出来了,因为断点都被禁用了。
启用断点
enable n
:启用编号为n的断点。
将编号为1的断点启用之后,我们使用r
命令,此时程序就在编号为1的断点位置停下来了。
逐过程
n
或next
:单条执行,相当于vs中的「F10」键,表示逐过程。
powershell
(gdb) b 18
Breakpoint 1 at 0x40055a: file mycode.c, line 18.
(gdb) r
Starting program: /home/Asi/study/day02/mybin
Breakpoint 1, main () at mycode.c:18
18 int result = 0;
(gdb) n
20 result = AddToTop(top);
以上代码,通过在第18行打上断点之后,输入r开始调试,再输入n,程序跳到了第20行,为什么不在第19行停下,因为19行为空格,停下没有意义。
逐语句
s
或step
:进入函数调用,相当于vs中的「F11」键,表示逐语句。
我们在上一步骤的基础上,输入s
,此时程序就进入了AddToTop()
函数里面。
查看变量的值
p + 变量
:打印变量值。注:只能再当前行显示,输入下一次命令时,就不会显示相关信息了。
如果想要像vs中监视窗口一样,一直可以观察到变量的变化状态,使用如下命令
display + 变量
:跟踪查看一个变量,每次停下来都显示它的值。
undisplay + 条目编号
:取消对先前设置的那些变量的跟踪。
info locals
:查看当前栈帧局部变量的值。
修改变量的值
set var
:修改变量的值
跳转
until + 行号
:用于使程序执行到指定行号的位置。
finish
:命令用于一直执行程序直到当前函数返回为止,然后在返回后停止执行。
使用 finish 命令可以跳过当前函数的剩余部分,直接返回到调用该函数的地方。
continue(或c)
:从一个断点直接运行到下一个断点处。
显示调用堆栈
breaktrace(或bt)
:显示调用堆栈。调用堆栈是程序执行期间函数调用的历史记录,它显示了函数调用的顺序以及每个函数在调用栈中的位置。