Windbg分析程序崩溃实践
1. 项目场景
本故事纯属虚构。
初入职场的小木,负责维护一个博客系统,后端采用C++编写,部署在Windows服务器上。刚刚熟悉完产品的小木,接到了后台服务的报警,服务器后端偶尔会程序崩溃。刚开始小木还有点慌张,脑子里面浮现出各种问题,这个是程序的bug吗?茫茫的代码如何寻找问题?log能看到线索吗?当冷静下来后,小木忽然想起前几天看的两篇文章<<Windbg调试----Windbg入门>>和<<Windows程序Dump收集>>,还没动手过呢,正好练习练习。
2. 收集Dump
首先小木想到了要定位到问题,得收集Dump。blogserver程序是64位程序,小木决定采用procdump64去收集dump。于是在产品服务器上运行了如下的命令, 将程序产生的dump生成到C:\dumps
目录下。
procdump.exe -ma blogserver.exe -t -e -o C:\dumps
接下小木就是一边review以前的代码,一边等待着Crash的出现。终于有一天出现啦,procdump64输出了如下的信息:
[15:34:17] Exception: C0000005.ACCESS_VIOLATION
[15:34:17] Unhandled: C0000005.ACCESS_VIOLATION
[15:34:17] Dump 1 initiated: C:\dumps\blogserver.exe_201115_153417.dmp
[15:34:17] Dump 1 writing: Estimated dump file size is 42 MB.
[15:34:17] Dump 1 complete: 42 MB written in 0.2 seconds
[15:34:17] Dump count reached.
ACCESS_VIOLATION
看来是访问了不可访问的内存,估计做过C++代码编写的程序员都碰到过这种内存访问问题。 小木将程序dump拷贝到了自己的办公机器上,准备用预先安装好的Windbg64位进行分析。
3. Windbg分析
小木根据之前学习的内容,先用Windbg 加载dump。用k
查看crash的堆栈,因为没有加载产品的符号信息,函数调用栈,没有显示出哪个函数调用导致程序crash了。这里补充一句,默认的产品发布采用Visual Studio Release模式发布,这个模式产品的符号信息将采用.pdb
文件单独保存,保证自己的符号信息不被泄露。
3.1 符号信息加载
- 小木先将之前产品的符号信息
blogserver.pdb
拷贝到调试机器的C:\blogserversymbols
目录下 - 创建一个微软的symbols的缓存目录
C:\windowssymbols
, 一般windows程序会加载很多微软的dll,而在分析crash的时候,也需要加载微软的symbols - 使用命令添加产品的symbols目录:
.sympath c:\blogserversymbols
- 使用命令添加了微软的symbols,并保存到指定的目录:
.sympath+ srv*C:\windowssymbols*http://msdl.microsoft.com/download/symbols
- 运行重新加载symbols:
.reload
以上的配置也可以保存到workspace中,以便下次继续使用。
3.2 寻找程序崩溃的代码
加载完symbols后,我们来看下程序调用栈:
0:000> k# Child-SP RetAddr Call Site
00 00000001`08b2f4e8 00007ffb`62c05237 ucrtbase!strnlen+0x3c
01 00000001`08b2f4f0 00007ffb`62bebf65 ucrtbase!cgetws_s+0x3b37
02 00000001`08b2f520 00007ffb`62beaa7c ucrtbase!_stdio_common_vfwscanf+0x3b15
03 00000001`08b2f570 00007ffb`62be9e7a ucrtbase!_stdio_common_vfwscanf+0x262c
04 00000001`08b2f5a0 00007ffb`62be863b ucrtbase!_stdio_common_vfwscanf+0x1a2a
05 00000001`08b2fac0 00007ffb`62beead1 ucrtbase!_stdio_common_vfwscanf+0x1eb
06 00000001`08b2faf0 00007ff6`78aa1c9f ucrtbase!_stdio_common_vfprintf+0x81
07 00000001`08b2fb60 00007ff6`78aa1cf8 blogserver!_vfprintf_l+0x3f [c:\program files (x86)\windows kits\10\include\10.0.18362.0\ucrt\stdio.h @ 644]
08 00000001`08b2fba0 00007ff6`78aa15b3 blogserver!fprintf+0x48 [c:\program files (x86)\windows kits\10\include\10.0.18362.0\ucrt\stdio.h @ 839]
09 00000001`08b2fbf0 00007ff6`78aa1d59 blogserver!LogStr+0x33 [c:\personal\test\blogserver\blogserver.cpp @ 10]
0a 00000001`08b2fc30 00007ff6`78aa2054 blogserver!main+0x39 [c:\personal\test\blogserver\blogserver.cpp @ 16]
0b (Inline Function) --------`-------- blogserver!invoke_main+0x22 [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78]
0c 00000001`08b2fc90 00007ffb`653f4034 blogserver!__scrt_common_main_seh+0x10c [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
0d 00000001`08b2fcd0 00007ffb`664a3691 kernel32!BaseThreadInitThunk+0x14
0e 00000001`08b2fd00 00000000`00000000 ntdll!RtlUserThreadStart+0x21
小木松了一口气,终于有点线索了,程序崩溃在函数LogStr
,根据里面的行数提示,找到那段代码:
void LogStr(std::string strContent)
{fprintf(stdout, strContent.c_str());
}
刚松了一口气,小木又疑惑起来,这个函数是用来打印博客标题的log的,一直都用,也测试过,怎么会偶尔导致程序崩溃呢? 小木睁大眼睛,(也许在读文章的你已经知道到什么问题了),作为新手,就这么一行代码,还是没有找到原因。
3.3 真相大白
小木接着看,是不是这个log内容比较奇特呢,决定先看一看strContent的内容。
小木切到fprintf那个frame:
0:000> .frame 08
08 00000001`08b2fba0 00007ff6`78aa15b3 blogserver!fprintf+0x48 [c:\program files (x86)\windows kits\10\include\10.0.18362.0\ucrt\stdio.h @ 839]
然后再查看当前的参数内容,知道了strContent
是Hello %sWindbg!
0:000> dv /t
struct _iobuf * _Stream = 0x00007ffb`62c584b8
char * _Format = 0x00000001`08b2fc60 "Hello %sWindbg!"
char * _ArgList = 0x00000001`08b2fc00 "Hello %sbg"
int _Result = 0n145947744
当看到%s
的时候,小木的编程直觉,瞬间反应过来了,这个%s
是格化式字符串。而这句话fprintf(stdout, strContent.c_str());
却将需要打印的strContent内容直接放在fprintf
的_Format
参数中, 这样%s
这个格式化串,将认为存在一个字符串参数,其实并没有,这样读取到的地址,将可能会出现ACCESS_VIOLATION
.
真相大白了,小木身心舒适,程序员的成就感涌上心头,对着空气微微一笑。小木知道以后还会碰到棘手的问题去处理,所以决定继续努力学习,所谓“台上一分钟,台下十年功”。
最后是个人微信公众号,文章CSDN和微信公众号都会发,欢迎一起讨论。
Windbg分析程序崩溃实践相关推荐
- Windbg分析dump崩溃
首先抓dump.在任务管理器->进程里面进行抓dump. 然后需要的原材料有dump.源码.pdb 打开windbg把源码路径和pdb路径添加进去. 需要打开的窗口包括线程窗口(Processe ...
- linux程序崩溃时调用链,Linux 获取并分析程序崩溃时的调用堆栈
下面是一个小例子,说明了程序出现段错误时,如何打印程序的堆栈信息. #include #include #include #include static void WidebrightSegvHand ...
- Linux程序崩溃分析(一)
引言 我们在做Linux开发时,常常会遇到程序崩溃的问题,这时会用gdb或者通过查看反汇编的方式去对程序进行分析,接下来,我们从底层的角度,去讲述如何分析程序崩溃的原因. 一.常见BUG 在进行分析前 ...
- windbg分析崩溃dmp
首先我们收集了程序崩溃的dump文件,然后将dump文件拖拽到windbg下,然后依次如下命令: 1.设置符号路径:.sympath srv*C:\symbols*http://msdl.micros ...
- 记一次 .NET 某医疗器械 程序崩溃分析
一:背景 1.讲故事 前段时间有位朋友在微信上找到我,说他的程序偶发性崩溃,让我帮忙看下怎么回事,上面给的压力比较大,对于这种偶发性崩溃,比较好的办法就是利用 AEDebug 在程序崩溃的时候自动抽一 ...
- 程序崩溃 分析工具_程序分析工具| 软件工程
程序崩溃 分析工具 A program analysis tool implies an automatic tool that takes the source code or the execut ...
- java 崩溃监控,求大神分析drwtsn32 监控javaee程序崩溃日记
当前位置:我的异常网» J2EE » 求大神分析drwtsn32 监控javaee程序崩溃日记 求大神分析drwtsn32 监控javaee程序崩溃日记 www.myexceptions.net 网 ...
- C语言常见的程序崩溃问题分析
文章目录 1. 常见的程序崩溃示例 2. 执行结果分析 1. 常见的程序崩溃示例 常见的崩溃类型有以下几种: 对空指针指向的内存非法写操作 对空指针指向的内存非法读操作 除0操作 大的临时变量或者递归 ...
- 揪出“凶手”——实战WinDbg分析电脑蓝屏原因
http://www.appinn.com/blue-screen-search-code/ 蓝屏代码查询器 – 找出蓝屏的元凶 11 文章标签: windows / 系统 / 蓝屏. 蓝屏代码查询器 ...
最新文章
- MS SQL专用管理员连接DAC
- Hibernate Session的delete()方法
- 进程间的通信方式:简介
- 解决pycharm安装包过程出现的问题:module 'pip' has no attribute 'main'
- axure怎么做5秒倒计时_装修隔音怎么做,进屋秒变“静音”模式
- 打破场景边界,PDFlux助你多领域表格提取
- python读取数据库数据类型_Python实现从SQL型数据库读写dataframe型数据的方法【基于pandas】...
- (软件工程复习核心重点)第十二章软件项目管理-第二节:进度计划
- 关于Jquery EasyUI中的DataGrid服务器端分页随记
- 【Anychat】理解POCO
- Visio实用技巧总结
- 一文吃透等额本息及其应用
- CTF-网络信息安全攻防学习平台(脚本关)
- python手机版下载-手机python下载
- 学3DMAX主要就业方向是什么?
- 计算机开机桌面空白,电脑开机桌面一片空白是怎么回事?
- 明日边缘:愈演愈烈的POS机网络犯罪
- 使用预装Win10的戴尔电脑最新恢复出厂设置方法
- 178页7万字智慧乡村大数据平台建设项目解决方案2022
- WinForm DataGridView实时更新表格数据
热门文章
- 库卡机器人外部紧急关断已按_东莞市库卡机器人系统维修中心
- 北大本科小妹妹:在北大“卷”了三年,才明白的四个道理…
- IT内审那点事之内部审核工作流程
- 2G|3G|4G网络速率知识普及
- 深度学习Week9-YOLOv5-C3模块实现(Pytorch)
- C++基础——抽象基类(ABC)
- 股票个人交易接口怎样导入excel 数据?
- Photoshop 基础知识 与 常用 快捷键
- 3.5mm 耳机插座 5脚
- oc调用python_引用ios-和引用ios相关的内容-阿里云开发者社区