【来自谢宝友同学的微信群】如何追踪stack overflow的issue?
本文是原「蜗窝讨论区」的历史存档(2017-09-06),来自版块「Linux kernel技术问答」,共 1 帖。讨论区已停止服务,此处仅供查阅。
问题: 我们开发应用的时候, 经常遇到爆栈和栈被破坏是个什么情况?怎么追踪这样的错误?
回答: 爆栈,个人理解就是栈大小不够了。例如,默认8M的栈空间,结果实际使用过程中,最长的调用链占用了超过8M的空间,导致撞上了保护墙,这时表现为段错误。
其原因一般是在函数中用了较大的局部变量,这些变量占用过多的栈空间。Linux内核有一个编译检测功能,可以检测函数局部变量过大的情况,并给出警告,这个应该是工具链提供的功能,用户态应该也可以使用。 也存在一些特殊情况,例如函数中数组或者变量越界,破坏了栈帧,导致在堆栈压栈退栈时候,将SP值破坏,看起来堆栈爆了。 栈被破坏,一般还是调用链上临时变量越界引起,但是也不能排除其他线程的野指针改写了堆栈里面的内容。另一种特殊情况,是内核,特别是驱动,在内核态中有内存野指针,或者在管理cache时出现问题。
具体如何分析有如下方法: 1、 创建时改变线程栈大小,这样现象可能会发生改变。甚至故障现象消失。 2、 创建一些无用的线程,在出问题的时候,用gdb连上去看看是不是栈里面的内容不是0。 3、 借用编译器的功能,在函数序言和尾声处加入钩子,在钩子中监控SP大小,一旦超过特定大小就报告,防止爆栈。 4、 直接拿着驱动走查代码,很多时候,走查代码是最快的查找故障的方法。 5、 在爆栈的时候,看看堆栈是不是全满了。直接看smaps文件里面,堆栈所在vma的rss字段即可。如果满了,用GDB连上去,把堆栈dump出来,手工找一找调用链也是可行的。
