一种栈溢出的场景分析和建议

场景介绍

有时候当你收到一个dump后,大多数情况可以通过k命令查找到导致栈溢出的函数。但是本文要讲的是,曾经碰到过的栈溢出(stackoverflow), 却无法直接通过k命令查看到当前的函数调用栈。 下面将介绍一个简单的方法,找到导致栈溢出的函数。

样例代码

先声明下,因为产品的实际分析不能够通过网络分享。下面的样例代码,实际上不会导致在上一章场景介绍中提到的问题,可以直接通过crash的栈查找到代码,本文只是通过这个例子来讲解如下场景的分析思路: 如果栈溢出了,通过k命令却无法查找到函数调用栈。

#include <iostream>
void Func(const char* pcsPara1, const char* pcsPara2){  char csTmpStr[1000] = "good";  std::cout << pcsPara1 << pcsPara2 << csTmpStr << std::endl;  Func(pcsPara1, pcsPara2);}
int main(){  Func("Hello ", "StackOverflow ");  return 0;}

样例分析

采用Windbg对dump进行分析。
第一步 通过!teb命令查看当前线程的基本信息, 大家应该都清楚,每一个线程都有自己的函数调用栈。这里着重看一下,这个线程的起始地址为StackBase (000000bfd6b00000), 栈的上限是StackLimit (000000bfd6a01000), 这里同样可以看出来栈是向低地址生长的,而且栈的大小大约为1MB.

0:000> !tebTEB at 000000bfd69b4000    ExceptionList:        0000000000000000    StackBase:            000000bfd6b00000    StackLimit:           000000bfd6a01000    SubSystemTib:         0000000000000000    FiberData:            0000000000001e00    ArbitraryUserPointer: 0000000000000000    Self:                 000000bfd69b4000    EnvironmentPointer:   0000000000000000    ClientId:             0000000000005fd8 . 0000000000000a98    RpcHandle:            0000000000000000    Tls Storage:          0000023ec056fdd0    PEB Address:          000000bfd69b3000    LastErrorValue:       0    LastStatusValue:      c000003a    Count Owned Locks:    0    HardErrorMode:        0

第二步 通过命令dps查看栈空间上值对应的符号信息。使用这个命令,是因为调用函数的时候会记录函数返回后要执行的下一条指令的地址,那么栈上就保留了函数的信息,通过这个命令就可以查找到对应的函数。(如果对函数调用过程还不熟悉的同学可以参考阅读<<你了解函数调用过程吗?>>)​​​​​​​

0:000> dps 000000bfd6a01000 000000bfd6b00000......000000bf`d6afd148  00007ff6`5a461755 StackOverflow!Func+0xa5......000000bf`d6afd588  00007ff6`5a461755 StackOverflow!Func+0xa5......000000bf`d6afd9c8  00007ff6`5a461755 StackOverflow!Func+0xa5......

第三步,可以通过栈上的值对应的符号信息,查找到可能的函数调用过程,比如这个例子看到多处调用StackOverflow!Func, 则可以对相应的代码处进行审查,得知这是一个栈溢出问题。

建议

其实对于栈溢出来说,很多情况都是函数非正常的循环调用导致, 此时修复这个bug即可。但也有可能是函数的局部变量空间过大,函数调用层数深。比如在一些领域禁止使用在堆上分配/使用内存,很多时候只能在栈上去申请,这个时候提高栈空间的默认值(1M),如下图将栈空间调整为4M。
图片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值