【软件开发底层知识修炼】十七 快速学习GDB调试四 使用GDB进行函数调用栈的查看
- 上一篇文章学习了如何使用GDB数据断点进行内存监测:【软件开发底层知识修炼】十五 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变
- 本篇文章继续上一篇文章的学习:如何使用GDB进行函数调用栈的查看
文章目录
- 1 backtrace和frame
- 2 使用GDB进行函数调用栈的查看的实际代码案例
- 3 总结
1 backtrace和frame
一般来说,查看函数调用栈,主要是为了研究函数的调用过程。
一般使用下面的命令进行查看:
backtrace
- 查看函数的调用顺序(函数调用栈的信息)
frame N
- 切换到栈编号为N的上下文中(具体栈编号是什么在下面的实际案例中会有)
info frame
- 查看当前函数调用栈帧的信息
至于什么是栈帧信息,大概就是下图的样子,这里不再多介绍,后面还会有文章学习函数栈帧的概念,或者推荐大家去阅读程序员的自我修养。
- 上面有一个info frame命令,我们在前几篇文章已经学习过info的几个命令。下面再介绍几个下图中的info命令:
2 使用GDB进行函数调用栈的查看的实际代码案例
我们还是给出以下代码,作为这次调试的代码:
frame.c
#include <stdio.h>int sum(int n)
{int ret = 0;if( n > 0 ){ret = n + sum(n-1);}return ret;
}int main()
{int s = 0;s = sum(10);printf("sum = %d\n", s);return 0;
}
上述代码很简单,sum函数是一个递归的求解过程,最终求得1+2+3+…+n
- 开始进行调试:
首先将程序编译,并打开gdb调试,这在前几篇文章已经做过很多次,大概如下图所示的步骤:
然后我们再sum函数处打一个断点,并给出条件,当n==0的时候断点成立
break sum if n==0
查看断点是否打上:info breakpoints
运行程序:continue
运行上述几个步骤后,程序运行到sum函数,并在sum函数递归调用到n==0的时候停止:
此时,函数调用被中断,我们现在来使用backtrace命令来查看之前sum函数的调用栈的顺序(左侧的#0 ,#1…就是栈的编号):
此时程序运行到n==0,本应该继续运行sum函数,但是却被我们的断点中断了。所以此时停在最后一层的sum函数递归调用上。且是停在sum函数中的第6行:
我们连续输入两次next,并且查看当前程序的栈信息:
程序运行到13行停下来了,这一行是本该return的。此时的函数栈中
n==0,ret==0
,这个ret就差返回给上一层函数调用了。现在我们来使用info registers查看当前的函数调用过程的各个寄存器的值,并使用info frame查看当前函数调用过程的函数栈帧的详细信息:
如上图,寄存器比较多,这里我们只关心一个寄存器,ebp,ebp寄存器保存的是调用这个函数的函数(也就是上一个函数,在这里是#1号栈对应的函数)栈帧基地址(old_ebp)。可以看到,此时的函数栈帧中的ebp地址为
0xbffff088
。注意你自己运行的话地址可能与我的不一样。这个地址中保存的是上一个函数,其实就是1号栈的基地址。我们使用以下命令来查看该地址处的内容:x /1bx 0xbffff088 //显示结果为:
如上图,红框内的内容,就是#1号栈的基地址。当然我们可以验证:连续输入两个next命令,程序就会把返回值返回给#1号栈的函数调用。那么此时再输入info args,n就等于1,因为此时位于#1号栈中。然后在输入info registers命令查看#1号栈的寄存器值信息,如下:
如上图,#1号栈中的ebp值为0xbffff0b8,与我们上面在#0号栈中查询的值是一样的。这与函数栈帧的理论也是完全相符的。
上面的调试内容,非常简单,我们并没有调试什么bug,而是通过上述内容,学习一些调试的技巧。
3 总结
- 本节内容学习如何使用GDB查看函数的调用栈信息。
本文章参考狄泰软件学院相关课程 想学习的可以加狄泰软件学院群, 群聊号码:199546072
学习探讨加个人(可以免费帮忙下载CSDN资源):
qq:1126137994
微信:liu1126137994
学习交流资源分享qq群:962535112
【软件开发底层知识修炼】十七 快速学习GDB调试四 使用GDB进行函数调用栈的查看相关推荐
- 【软件开发底层知识修炼】十八 快速学习GDB调试五 使用GDB进行调试的一些小技巧
上一篇文章学习了如何使用GDB进行函数调用栈的查看:[软件开发底层知识修炼]十六 快速学习GDB调试四 使用GDB进行函数调用栈的查看 本篇文章是GDB调试快速学习系列的最后一篇.将综合前几篇文章做一 ...
- 【软件开发底层知识修炼】十六 快速学习GDB调试三 使用GDB的数据断点监测变量是否改变
上一篇文章我们学习了如何使用GDB进行软件断点调试和硬件断点调试:[软件开发底层知识修炼]十五 快速学习GDB调试二 使用GDB进行断点调试 本篇文章继续上一篇文章的学习,如何使用GDB的数据断点监测 ...
- 【软件开发底层知识修炼】十五 快速学习GDB调试二 使用GDB进行断点调试
上一篇文章我们学习了使用GDB的最基本方法:[软件开发底层知识修炼]十四 快速学习GDB调试一 入门使用 本篇文章将学习GDB的断点调试.断点调试是一种非常重要的调试方法. 文章目录 1 断点类型 2 ...
- 【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用
前面几篇文章学习了链接器相关的内容.现在开始来学习GDB调试.我们的目的是通过这几篇文章将GDB调试完全学会. 文章目录 1 为什么需要GDB 2 GDB 的常规应用 3 GDB调试程序实例 4 总结 ...
- 【软件开发底层知识修炼】十九 GDB调试从入门到熟练掌握超级详细实战教程学习目录
本文记录之前写过的5篇关于GDB快速学习的文章,从第一篇开始学习到最后一篇,保证可以从入门GDB调试到熟练掌握GDB调试的技巧. 学习交流加 个人qq: 1126137994 个人微信: liu112 ...
- 【软件开发底层知识修炼】二十七 C/C++中的指针与数组是不同的
上几篇文章学习了ABI-应用程序二进制接口:[软件开发底层知识修炼]二十六 ABI-应用程序二进制接口 学习总结文章目录 本篇文章就指针与数组的联系与区别来学习学习 文章目录 1 疑问 2 指针与数组 ...
- 【软件开发底层知识修炼】二十六 ABI-应用程序二进制接口 学习总结文章目录
前面学习了ABI的知识,感觉受益良多.对底层与编译器有更加深刻的认识,为此这里将前面写过的关于ABI 的文章给列出来,方便学习与翻阅. [软件开发底层知识修炼]二十一 ABI-应用程序二进制接口一 [ ...
- 【软件开发底层知识修炼】二十八 C/C++中volatile的作用
上一篇文章学习了C/C++中的指针与数组的区别,点击链接进行查看:[软件开发底层知识修炼]二十七 C/C++中的指针与数组是不同的 本篇文章将学习volatile关键字在C/C++中的作用 文章目录 ...
- 【软件开发底层知识修炼】二十五 ABI之函数调用约定二之函数返回值为结构体时的约定
上一篇文章学习了几种函数调用约定的区别,点击链接查看上一篇文章:[软件开发底层知识修炼]二十四 ABI之函数调用约定 本篇文章继续学习函数调用约定中,关于函数返回值的问题.当函数返回值为结构体时,函数 ...
最新文章
- Python 抖音机器人,论如何在抖音上找到漂亮小姐姐?
- adb 显示手机分辨率
- 6_分布式训练框架Horovod使用(20190111)
- vc++基于颜色直方图的图像检索,含代码
- 计算机软件员证书用途,软考证书的五大好处(详解)
- mysql通配符查询 性能_使用mysql5.7新特性解决前通配符查询性能问题
- 为 Angular service 注册 provider 的三种方式
- FPGA时钟激励编写(方法三)
- 游戏角色坐标的保存间隔_游戏岗位看这里鸭——
- multipart/form-data与application/octet-stream的区别、application/x-www-form-urlencoded
- C语言程序实验01,广西科技大学理学院《C语言程序设计与算法语言》实验01: 熟悉开发环境.pdf...
- 电源大师课笔记 1.2
- 动易 当前服务器不允许上传文件,动易网站详细安说明及常见疑难解答.doc
- 联想微型计算机m910q,联想ThinkCentre M910x迷你台式机 获最佳创新产品奖
- 编写函数:笛卡尔坐标系(Append Code)
- [Fabric] 第11章 Fabric CA应用与配置
- windows环境下anaconda-navigaotr出现adding featured channels一直打不开的情况
- Vlc.DotNet C#音视频播放器使用说明及简单实例
- android会中病毒吗,安卓手机浏览网页中病毒几率多大
- 关于unity区域截图像素越界解决办法