gdb调试程序时跳进函数和跳出函数

前言

说实话平时在Windows平台上开发,gdb调试用的并不是很多,但是一些在linux平台才会出现的BUG,或者在linux运行时宕机产生了core文件,这些还是需要使用gdb调试的,之前的文章《linux环境下服务器程序的查看与gdb调试》列举了常用的gdb命令,基本上调试一些core文件和简单bug使用这些命令足以了,但是新的需求总是会出现。

新的需求也很常见,就是跳进一个函数,调试一部分代码后还要跳出这个函数,一般情况就是这个函数特别长,调试前几行已经明白函数的逻辑和用意,如果使用 next 命令逐行运行需要花费较多时间,所以需要跳出函数回到调用的位置,这两个操作在Visual Studio中的快捷键分别是F11Shift+F11,使用起来非常的方便,其实在gdb调试的过程中也有对应的命令,分别是step(s)finish(fin),括号中的内容为命令的简写,此外还有一个return命令也可以使函数返回,接下来可以看一下它们的区别。

测试代码

测试的代码很简单,只需要写一个简单的函数,并且在主函数中调用这个函数即可,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

int son_func()
{
int a = 100;
int b = 1;
return a + b;
}

int main()
{
int i = 10;
cout << i << endl;

int result = son_func();

cout << result << endl;
}

代码编译

编译代码时只需要注意一点,那就是加上-g选项,否则可能会影响调试:

1
albert@localhost#11:56:18#/home/albert/gdbtest]$g++ -g stepfinish.cpp -o stepfinishtest

step/finish组合

这个组合不会影响函数的运行结果,简单的调试过程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[albert@localhost#11:32:17#/home/albert/gdbtest]$gdb stepfinishtest
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6)
Copyright (C) 2010 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/albert/gdbtest/stepfinishtest...done.
(gdb) start
Temporary breakpoint 1 at 0x400809: file stepfinish.cpp, line 13.
Starting program: /home/albert/gdbtest/stepfinishtest

Temporary breakpoint 1, main () at stepfinish.cpp:13
13 int i = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.209.el6_9.2.x86_64 libstdc++-4.4.7-23.el6.x86_64
(gdb) n
14 cout << i << endl;
(gdb) n
10
16 int result = son_func();
(gdb) step
son_func () at stepfinish.cpp:6
6 int a = 100;
(gdb) finish
Run till exit from #0 son_func () at stepfinish.cpp:6
0x0000000000400831 in main () at stepfinish.cpp:16
16 int result = son_func();
Value returned is $1 = 101
(gdb) n
18 cout << result << endl;
(gdb) n
101
19 }
(gdb) c
Continuing.

Program exited normally.
(gdb)

首先使用start命令启动程序,然后使用next(n)命令让程序运行到调用函数son_func()所在的行,使用step命令进入函数,我们看到a的值为100,假设这时我们想回到这个函数被调用的位置,直接敲finish命令就可以,函数完整的执行并返回结果101,最后连续执行next(n)命令,程序正常退出,整个过程只是调试查看数据,并没有改变程序运行结果。

step/return组合

这个组合有可能会影响函数的运行结果,具体要看return命令使用的位置和返回的参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[albert@localhost#11:53:42#/home/albert/gdbtest]$gdb stepfinishtest
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-83.el6)
Copyright (C) 2010 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/albert/gdbtest/stepfinishtest...done.
(gdb) start
Temporary breakpoint 1 at 0x400809: file stepfinish.cpp, line 13.
Starting program: /home/albert/gdbtest/stepfinishtest


Temporary breakpoint 1, main () at stepfinish.cpp:13
13 int i = 10;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.209.el6_9.2.x86_64 libstdc++-4.4.7-23.el6.x86_64
(gdb) n
14 cout << i << endl;
(gdb) n
10
16 int result = son_func();
(gdb) step
son_func () at stepfinish.cpp:6
6 int a = 100;
(gdb) n
7 int b = 1;
(gdb) return 119
Make son_func() return now? (y or n) y
#0 0x0000000000400831 in main () at stepfinish.cpp:16
16 int result = son_func();
(gdb) n
18 cout << result << endl;
(gdb) print result
$1 = 119
(gdb) c
Continuing.
119

Program exited normally.
(gdb)

首先同样使用start命令启动程序,然后使用next(n)命令让程序运行到调用函数son_func()所在的行,使用step命令进入函数,我们看到a的值为100,这时再敲入next(n)命令让程序运行一步,可以看到b的值为1,假设这时我们想返回一个自定义值而不返回a+b的结果,可以直接敲命令return 119,表示直接返回119这个值,再打印返回值变量result发现是值119,跳出函数的同时,程序运行结果也已经被我们改变了。

总结

  1. gdb中跳入函数的命令是step,相当于Visual Studio中的快捷键F11
  2. gdb中跳出函数的命令是finish,相当于Visual Studio中的快捷键Shift+F11,函数完整执行后返回
  3. gdb中还有一个直接返回的命令是return,它会跳过当前函数后面的语句直接返回,返回值可以自定义,紧跟在return命令后面即可
Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客