C++栈回溯原理
2021/10/27 22:11:04
本文主要是介绍C++栈回溯原理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
我们在使用VS调试源代码或使用Windbg调试exe程序时,遇到异常,调试器就会中断下来,然后就能查看到此刻的函数调用堆栈。软件是执行到某一句机器代码产生了异常,可以看成执行了某一句汇编代码产生了异常,通过一句汇编代码,是如何将所在线程此刻完整的函数调用堆栈给回溯进来的呢?下面我们就来讲讲栈回溯的原理。
要搞清楚栈回溯的原理,需要对照着函数调用时的栈分布情况来看:
1、函数入口处的汇编代码
对照着上图,看一下函数入口的ebp和esp寄存器操作。
ebp - 函数栈基址寄存器,esp - 函数栈顶地址寄存器。函数占用的栈空间(地址范围)就在esp中的栈顶地址到ebp中的栈基址之间,函数的栈空间在函数入口处就进行分配了。
在每个函数的入口处都会有下面两句代码:
push ebp mov ebp,esp
push的是主调函数的ebp,当前主调函数的栈顶地址esp,给被调函数ebp,即主调函数在调用函数时的栈顶地址就是被调函数的栈基址ebp。从栈内存分布来看,被调函数的栈基址,就是主调函数的栈基址值存放在栈内存上的内存地址。
2、函数退出处的汇编代码
每个函数退出处都会有下面两句汇编代码:(return之前的汇编代码)
mov esp,ebp pop ebp
被调函数即将退出时,将自己(被调函数)的栈基址给主调函数的esp,即作为主调函数当前的栈顶地址。然后从栈中将主调函数的栈基址值拿出来,放到ebp寄存器中。
3、栈回溯的过程
首先通过当前发生异常的那句汇编代码的地址(代码段地址),通过遍历当前程序中所有函数的地址范围,即可得知当前发生异常的汇编指令位于哪个函数中。
就是以当前ebp寄存器中的值作为栈内存地址,该地址指向的栈内存中的4字节内容就是主调函数的栈基址值ebp(先记录着,为下一轮推算做准备),向下偏移4个字节的内存中存放着主调函数的返回地址,根据返回地址遍历当前程序中的函数地址范围,确定主调函数是哪个函数。
上面得到了主调函数的栈基址ebp,依次向上推算,确定更上一层的主调函数,这样就将函数调用栈给回溯出来了。
这篇关于C++栈回溯原理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享