linux进阶16——GDB(二):启动程序和设置断点

1. 启动程序

根据不同场景的需要,GDB 调试器提供了多种方式来启动目标程序,其中最常用的就是 run 指令,其次为 start 指令。也就是说,run 和 start 指令都可以用来在 GDB 调试器中启动程序,它们之间的区别是:

  • 默认情况下,run 指令会一直执行程序,直到执行结束。如果程序中手动设置有断点,则 run 指令会执行程序至第一个断点处;
  • start 指令会执行程序至 main() 主函数的起始位置,即在 main() 函数的第一行语句处停止执行(该行代码尚未执行)。

可以这样理解,使用 start 指令启动程序,完全等价于先在 main() 主函数起始位置设置一个断点,然后再使用 run 指令启动程序。另外,程序执行过程中使用 run 或者 start 指令,表示的是重新启动程序。

在进行 run 或者 start 指令启动目标程序之前,还可能需要做一些必要的准备工作,大致包括以下几个方面:

  • 如果启动 GDB 调试器时未指定要调试的目标程序,或者由于各种原因 GDB 调试器并为找到所指定的目标程序,这种情况下就需要再次手动指定;
  • 有些 C 或者 C++ 程序的执行,需要接收一些参数(程序中用 argc 和 argv[] 接收);
  • 目标程序在执行过程中,可能需要临时设置 PATH 环境变量;
  • 默认情况下,GDB 调试器将启动时所在的目录作为工作目录,但很多情况下,该目录并不符合要求,需要在启动程序手动为 GDB 调试器指定工作目录。
  • 默认情况下,GDB 调试器启动程序后,会接收键盘临时输入的数据,并将执行结果会打印在屏幕上。但 GDB 调试器允许对执行程序的输入和输出进行重定向,使其从文件或其它终端接收输入,或者将执行结果输出到文件或其它终端。

如下示例程序main.c:

#include<stdio.h>
int main(int argc,char* argv[])
{
    FILE * fp;
    if((fp = fopen(argv[1],"r")) == NULL){
        printf("file open fail");
    }
    else{
        printf("file open true");
    }
    return 0;
}

执行gdb调试的步骤如下所示:

2. 设置断点

断点(BreakPoint),可以理解为障碍物,人遇到障碍物不能行走,程序遇到断点就暂停执行。

在 GDB 调试器中对  C、C++ 程序打断点,最常用的就是 break 命令,有些场景中还会用到 tbreak 或者 rbreak 命令。

示例程序:

#include<stdio.h>
int main(int argc,char* argv[])
{
    int num = 1;
    while(num<100)
    {
        num *= 2;
    }
    printf("num=%d",num);
    return 0;
}

2.1 break

break 命令(可以用 b 代替)常用的语法格式有以下 2 种。

1)(gdb) break location     // b location
2)(gdb) break ... if cond   // b .. if cond

1)第一种格式中,location 用于指定打断点的具体位置,其表示方式有多种,如表 1 所示

2) 第二种格式中,... 可以是表 1 中所有参数的值,用于指定打断点的具体位置;cond 为某个表达式。整体的含义为:每次程序执行到 ... 位置时都计算 cond 的值,如果为 True,则程序在该位置暂停;反之,程序继续执行。

具体用法如下:

(gdb) l
1 #include<stdio.h>
2 int main(int argc,char* argv[])
3 {
4     int num = 1;
5     while(num<100)
6     {
7         num *= 2;
8     }
9     printf("num=%d",num);
10   return 0;
(gdb)
11 }
(gdb) b 4          <-- 程序第 4 行打断点
Breakpoint 1 at 0x1138: file main.c, line 4.
(gdb) r              <-- 运行程序,至第 4 行暂停
Starting program: /home/ubuntu64/demo/main.exe

Breakpoint 1, main (argc=1, argv=0x7fffffffe078) at main.c:4
4     int num = 1;
(gdb) b +1        <-- 在第 4 行的基础上,在第 5 行代码处打断点
Breakpoint 2 at 0x55555555513f: file main.c, line 5.
(gdb) c             <-- 继续执行程序,至第 5 行暂停
Continuing.

Breakpoint 2, main (argc=1, argv=0x7fffffffe078) at main.c:5
5     while(num<100)
(gdb) b 7 if num>10     <-- 如果 num>10 在第 7 行打断点
Breakpoint 3 at 0x555555555141: file main.c, line 7.
(gdb) c               <-- 继续执行
Continuing.

Breakpoint 3, main (argc=1, argv=0x7fffffffe078) at main.c:7
7         num *= 2;       <-- 程序在第 7 行暂停
(gdb) p num      <-- p 命令查看 num 当前的值
$1 = 16             <-- num=16

2.2 tbreak

tbreak 命令可以看到是 break 命令的另一个版本,tbreak 和 break 命令的用法和功能都非常相似,唯一的不同在于,使用 tbreak 命令打的断点仅会作用 1 次,即使程序暂停之后,该断点就会自动消失。

tbreak 命令的使用格式和 break 完全相同,有以下 2 种:

1、(gdb) tbreak location
2、(gdb) tbreak ... if cond

其中,location、... 和 cond 的含义都和 break 命令中的参数含义相同,即表 1 也同样适用于 tbreak 命令。

仍以上面的程序为例,具体用法如下:

[root@localhost day2]# gdb test1
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/gdb/day2/test1...done.
(gdb) l
1	#include<stdio.h>
2	int main(int argc,char* argv[])
3	{
4	    int num = 1;
5	    while(num<100)
6	    {
7	        num *= 2;
8	    }
9	    printf("num=%d",num);
10	    return 0;
(gdb) tbreak 7
Temporary breakpoint 1 at 0x40051a: file test1.c, line 7.
(gdb) r
Starting program: /home/gdb/day2/test1 

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe578) at test1.c:7
7	        num *= 2;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-323.el7_9.x86_64
(gdb) p num
$1 = 1
(gdb) c
Continuing.
num=128[Inferior 1 (process 1842) exited normally]
(gdb) 

2.3 rbreak

和 break 和 tbreak 命令不同,rbreak 命令的作用对象是 C、C++ 程序中的函数,它会在指定函数的开头位置打断点。

tbreak 命令的使用语法格式为:

(gdb) tbreak regex

其中 regex 为一个正则表达式,程序中函数的函数名只要满足 regex 条件,tbreak 命令就会其内部的开头位置打断点。值得一提的是,tbreak 命令打的断点和 break 命令打断点的效果是一样的,会一直存在,不会自动消失。

具体用法:

[root@localhost day2]# gdb test2
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/gdb/day2/test2...done.
(gdb) l 0
1	#include <stdio.h>
2	
3	void rb_one()
4	{
5		printf("rb_one\n");
6	}
7	
8	void rb_second()
9	{
10		printf("rb_second");
(gdb) 
11	}
12	
13	int main(int argc,char* argv[])
14	{
15		rb_one();
16	
17		rb_second();
18		return 0;
19	}
(gdb) 
Line number 20 out of range; test2.c has 19 lines.
(gdb) rbreak rb_*    <--匹配所有以 rb_ 开头的函数
Breakpoint 1 at 0x400546: file test2.c, line 5.
void rb_one();
Breakpoint 2 at 0x400557: file test2.c, line 10.
void rb_second();
(gdb) r
Starting program: /home/gdb/day2/test2 

Breakpoint 1, rb_one () at test2.c:5
5		printf("rb_one\n");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-323.el7_9.x86_64
(gdb) c
Continuing.
rb_one

Breakpoint 2, rb_second () at test2.c:10
10		printf("rb_second");
(gdb) c
Continuing.
rb_second[Inferior 1 (process 1896) exited normally]
(gdb) c
The program is not being run.
(gdb) 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值