首页
社区
课程
招聘
[原创]调试实战 | 记一次有教益的递归栈查看
发表于: 2024-1-15 07:27 10784

[原创]调试实战 | 记一次有教益的递归栈查看

2024-1-15 07:27
10784

最近,遇到了一个由于递归导致的卡死问题。这个问题非常有意思,值得总结。

你知道什么情况下无限递归会卡死,而不崩溃吗?你知道递归层数过多时,如何找到导致递归调用的函数吗?你知道如何快速找到关键线程吗?你知道如何附加到一个正在被调试的进程吗?你知道如何在 windbg 中显示指定数量的栈帧吗?

带着这些疑问,一起来看看这个非常有意思的问题吧。

说明: 文章末尾有这些问题的答案,可以直接跳到末尾查看。

程序在执行某个功能时,迟迟不能完成,通过任务管理器可以发现 CPU 使用率比较高(12.47%),大概耗尽了一个核心(机器是八核的,每个核心占 12.5%)。
high-cpu

心中暗喜,大概率是遇到了死循环,应该很好解决。赶紧用 vs 附加上去看看。

附加到被调试进程后,手动暂停,然后通过并行堆栈找到可疑线程。

温馨提示: 可以通过 调试 -> 窗口 -> 并行堆栈 打开并行堆栈视图,也可以使用快捷键 Ctrl+Shift+D, S 打开 。

一般情况下调用栈最长的线程就是可疑线程。即使不是,也可以在并行堆栈视图中快速切换线程。相比于手动一个个切换线程,并行堆栈简直是太方便了!
view-thread-stack

通过并行堆栈视图,可以观察到当前线程的调用栈非常深,已经超出了 vs 所支持的最大栈帧数。仔细观察调用栈,可以发现 00007ffc9dcb3cb5 这个地址会重复出现,说明这很可能是一个递归问题。

然而,只知道这是一个递归问题还不够,我们需要找到引发递归调用的函数。如果能看到完整的调用栈,那么就可以找到罪魁祸首了。由于 vs 不能显示更多的调用栈帧,我们可以请老朋友 windbg 出马。

启动 windbg,以 Noninvasive 模式附加到被调试进程(由于该进程正在被 vs 调试,如果不以 Noninvasive 模式附加,windbg 无法成功附加)。
windbg-noninvasive-attach

附加成功后,通过 ~~[12544]s 切换到目标线程,没想到报错了。
windbg-switch-thread-error

没关系,直接切不过去,还有其它方法可以找到目标线程。可以简单粗暴的使用 ~* k 命令显示所有线程的调用栈,然后根据调用栈判断哪个线程是目标线程,也可以通过 !runaway 查看所有线程的运行时间,根据运行时间长短快速找出目标线程。

windbg 中输入 !runaway 可以查看所有线程的运行时间。一般,CPU 占用率越高的线程,运行时间也越长。
windbg-runaway

可以发现 0 号线程运行时间最长,然后是 32 号线程。先切换到 0 号线程,执行 k 命令查看调用栈,发现是主线程(一般情况下 0 号线程都是主线程),不是我们关心的线程。再执行 ~32s 切换到运行时间排名第二的线程,然后执行 k 命令查看调用栈,发现与在 vs 中看到的调用栈吻合,32 号线程是目标线程了。

**说明: ** 当时比较着急,忘了 windbg 中默认使用十六进制。如果执行 ~~[0n12544]s 即可正常切换过去了。0n 表示使用十进制。

switch-to-0n12544-successfully

找到对应的线程后,接下来的任务是查看完整调用栈。

默认情况下,windbgk 命令最多只显示 256 个调用栈帧,最大的栈帧号是 ff,从 0 开始计数。
windbg-k-output-default

我们可以在 windbg 中执行 kN来指定要显示的栈帧数,如果 N 足够大,那么应该可以显示出完整的调用栈。

先尝试输入 k200,发现看不到头,再试试 k2000,依然看不到头,k5000 依然看不到头(这调用栈不是一般的深啊~)。 直接输入 k50000,这次应该够了吧?没想到报错了。
windbg-k50000-error

根据提示可知,可以输入的最大值是 0xffff。在 windbg 中输入 k0xffff,耐心等待一会儿就可以看到完整的调用栈了。如下图:
view-full-callstack-in-windbg

说明: 不要输入 kffff,因为会被解释为 kf fff,第一个 f 会被解释为选项,用来显示两个栈帧的间距。windbg-k-command-help


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 11
支持
分享
最新回复 (2)
雪    币: 3573
活跃值: (31026)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2024-1-15 11:29
1
雪    币: 193
活跃值: (2696)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
点赞支持
2024-1-15 17:04
0
游客
登录 | 注册 方可回帖
返回
//