近日,我们视频平台提交基线测试时,出现录像下载失败崩溃的现象,通过仔细调试发现其是一个很典型的DLL HELL引发的栈溢出,由于在我们的项目中,引用了大量的DLL,而且有很多DLL是多方引用的,很容易出现版本不一致的问题,一般这种问题极难排查,需要耗费大量精力,现将此排查过程记录下,希望对后面类似问题的排查有所帮助。

一、首先观察问题出现的现象,并确定能否复现及复现的操作步骤

经过多方测试及确认,其复现步骤如下:

1.      登录平台客户端,并切换至录像回放tab页

2.      选择一个监控点,并进行录像搜索

3.      点击录像下载按钮,选择录像下载开始结束时间

4.      点击确定,客户端崩溃

java 异常堆栈缩减 堆栈溢出异常_DLL

二、 使用调试器附加运行,确定崩溃原因及崩溃代码行

一般我会使用windbg附加上去执行,当客户端崩溃后,会中断到调试器。

此时windbg输出如图所示:

java 异常堆栈缩减 堆栈溢出异常_windbg_02

首先观察到是错误码,很常见的access violation 0xc0000005,代表访问违例,一般这种问题是访问了错误的内存地址导致。最下面那行输出的是当前所执行到的代码,可以从图中看到,都是错误的值,这种现象意味着指令指针寄存器,EIP的值指向了错误的内存地址,一般出现这种问题最常见的有两种情况,一是EIP所执行的模块已经被卸载,二是发生了栈溢出,覆盖了栈上的返回地址。

可以输入r命令,查看下当前寄存器的值:

java 异常堆栈缩减 堆栈溢出异常_java 异常堆栈缩减_03

(传了几张图片发现还有水印。。)

可以看到EIP为0,比较麻烦的是ebp也为0,因为我们要看调用栈的话,windbg会借助ebp帮我们确定,如果ebp也错误了,我们查看调用栈就会遇到一定的麻烦。

 

输入k,果然不出所料,调用栈信息已经无法正常输出了

java 异常堆栈缩减 堆栈溢出异常_DLL_04

c

值得庆幸的是,esp的值看起来还有意义,我们借助esp的值来手动重建调用栈。

试探的看下esp指向的栈数据,输入dps esp

 


java 异常堆栈缩减 堆栈溢出异常_DLL_05