使用Windbg分析dump文件定位软件异常的方法与操作步骤
目录
1、Windbg简介
2、Windbg版本与安装
3、Windbg常用命令
4、静态分析dump文件的一般步骤
4.1、查看异常类型
4.2、使用.ecxr命令切换到发生异常的线程上下文,查看发生异常的那条汇编指令
4.3、使用kn/kv/kp命令查看异常发生时的函数调用堆栈
4.4、使用lm命令查看模块的时间戳,找到对应的pdb文件,设置到Windbg中
5、实战问题分析实例说明
6、使用Windbg详细分析dump文件,展现完整分析过程
6.1、查看异常类型和发生崩溃的汇编指令,初步分析
6.2、使用kn/kv/kp命令查看函数调用堆栈
6.3、找到pdb文件,设置到windbg中,查看完整的函数调用堆栈
6.4、可以将C++源代码路径设置到Windbg中,Windbg会自动跳转到源代码行号上
6.5、有时需要查看函数调用堆栈中函数的局部变量或C++类对象中变量的值
6.6、有时可能需要使用IDA去查看二进制文件的汇编代码上下文去辅助分析
7、最后
C++软件异常排查从入门到精通系列教程(核心精品专栏,订阅量已达600多个,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C++实战专栏(重点专栏,专栏文章已更新500多篇,订阅量已达数百个,欢迎订阅,持续更新中...)
https://blog.csdn.net/chenlycly/article/details/140824370C++ 软件开发从入门到实战(重点专栏,专栏文章已更新300多篇,欢迎订阅,持续更新中...)
https://blog.csdn.net/chenlycly/category_12695902.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)
https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)
https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)
https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)
https://blog.csdn.net/chenlycly/category_2276111.html 一般我们会在软件中添加异常捕获模块,当软件发生异常时,异常捕获模块会感知到异常并自动生成包含异常上下文信息的dump文件,事后把dump文件拿来用Windbg打开进行分析,这是我们排查软件异常最常用、最有效的方式。本文就来详细讲解一下如何使用Windbg分析dump文件去排查软件异常,并给出了一个实战问题分析实例。
1、Windbg简介
Windbg是微软提供的Windows平台下强大的用户态和内核态调试器,给我们分析Windows平台上软件的异常提供了极大的便利与强有力的支持,比原始的直接查看代码分析异常的效率要来的高的多。Windbg甚至在某些方面要比微软的Visual Studio还要强大,是日常工作中分析软件异常最常用的工具。作为Windows平台的开发人员,有必要学会使用该工具。
Windbg在排查内存越界、内存访问违例、stack overflow线程栈溢出、空指针与野指针、死循环、死锁、高CPU占用、内存泄露、GDI对象泄露、函数调用约定不一致导致的栈不平衡等异常问题方面,有着独到的优势,比直接查看日志、走读代码去排查的效率要高的多。关于引发C++软件异常的常见原因,我之前做过详细的总结,可以查看我的文章:引发C++软件异常的常见原因分析与总结(实战经验分享)https://blog.csdn.net/chenlycly/article/details/124996473
Windbg分析软件异常问题主要有两种方式,一种是使用Windbg静态分析dump文件,另一种是将Windbg附加到目标程序进程上进行动态调试。一般会在程序中安装异常捕获模块,当程序发生异常时异常捕获模块可以感知到,并自动生成包含异常上下文信息的dump文件。事后开发人员取来dump文件,用Windbg打开该dump文件进行静态分析。
如果没有捕获到异常没有生成dump文件,或者通过dump文件分析不出来问题时,则需要将Windbg附加到目标程序进程上进行动态调试。有些异常崩溃,程序中安装的异常捕获模块捕获不到,就可以尝试将Windbg附加到目标进程上,让Windbg和目标程序一起跑,一旦程序发生异常,正在调试该程序进程的Windbg会第一时间感知到并中断下来,然后就可以查看此时的函数调用堆栈进行分析了。此外,还可以在Windbg中设置断点,直接在Windbg中进行断点调试。
关于dump文件的分类以及dump文件生成方式的详细说明,可以查看我之前写的文章:
dump文件类型与dump文件生成方法详解https://blog.csdn.net/chenlycly/article/details/140742911 关于何时使用Windbg静态分析dump文件、何时将Windbg附加到目标程序进程上进行动态调试,我之前写过专题文章,可以查看:
何时使用Windbg静态分析?何时使用Windbg动态调试?https://blog.csdn.net/chenlycly/article/details/131806819
2、Windbg版本与安装
常用的Windbg版本有6.0老版本、10.0新版本以及Windbg PreView版本。Windbg 6.0版本是比较老的版本,可以下载到绿色版本。Windbg 10.0和Windbg Preview都是新版本,相对于6.0老版本,要智能很多,不再需要输入各种复杂的Windbg命令,只要点击一些超链接就可以相关信息了。
Windbg 10.0已经内置到Windows SDK的安装包中,这个安装包可以到微软的官方网站上下载,安装时只需要勾选安装Debugging Tools for Windows选项:(上图就是Windbg 10.0的界面)
就是安装Windbg10.0版本了。关于Windbg10.0安装包的获取与安装的详细说明,可以查看我之前写的文章:
Windbg安装与使用详解https://blog.csdn.net/chenlycly/article/details/120631007
Windbg PreView版本则需要到Windows自带的应用商店中下载:(上图就是Windbg preview的界面)
Windbg PreView版本相对于Windbg 10.0,界面要酷炫很多,功能上相差无几,增加了一些新功能。我平时主要用Windbg 10.0。
在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)
专栏1:(该精品技术专栏的订阅量已达到600多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,已经更新到200篇以上!欢迎订阅!)
C++软件调试与异常排查从入门到精通系列文章汇总https://blog.csdn.net/chenlycly/article/details/125529931
本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!
考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!
专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!
专栏2:(本专栏涵盖了C++多方面的内容,是当前重点打造的专栏,订阅量已达300多个,专栏文章已经更新到500多篇,持续更新中...)
C/C++实战进阶(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_11931267.html
以多年的开发实战为基础,总结并讲解一些的C/C++基础与项目实战进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域多个方面的内容,包括C++基础及编程要点(模版泛型编程、STL容器及算法函数的使用等)、数据结构与算法、C++11及以上新特性(不仅看开源代码会用到,日常编码中也会用到部分新特性,面试时也会涉及到)、常用C++开源库的介绍与使用、代码分享(调用系统API、使用开源库)、常用编程技术(动态库、多线程、多进程、数据库及网络编程等)、软件UI编程(Win32/duilib/QT/MFC)、C++软件调试技术(排查软件异常的手段与方法、分析C++软件异常的基础知识、常用软件分析工具使用、实战问题分析案例等)、设计模式、网络基础知识与网络问题分析进阶内容等。
专栏3:
C++常用软件分析工具从入门到精通案例集锦汇总(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/article/details/131405795
常用的C++软件辅助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!
专栏4:
VC++常用功能开发汇总(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/article/details/124272585
将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。
专栏5:
C++ 软件开发从入门到精通(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_12695902.html
根据多年C++软件开发实践,详细地总结了C/C++软件开发相关技术实现细节,分享了大量的实战案例,很有实战参考价值。
3、Windbg常用命令
在Windbg中主要通过Windbg命令(或者点击Windbg中显示的超链接)去查看dump文件中的线程与函数堆栈等信息,常用的Windbg命令有g(继续运行)、.excr(切换到发生异常的线程)、kn/kv/kp(查看线程的函数调用堆栈)、~ns(切换到n号线程)、lm(查看模块信息)、!analyze -v(详细分析异常)、.dump(导出dump文件)、bp/bl/ba/bc(查看/设置断点)等。关于这些常用命令的详细说明,可以查看我之前写文章:
Windbg常用命令详解https://blog.csdn.net/chenlycly/article/details/125508027 更多、更全面的Windbg命令汇总,可以查看我的文章:
Windbg调试命令汇总https://blog.csdn.net/chenlycly/article/details/51711212
下面在讲到具体的问题分析实例时,会讲到上述常用命令,此处就不详细展开了。
4、静态分析dump文件的一般步骤
使用Windbg静态分析dump文件时,首先查看发生异常的类型(比如Integer divide-by-zero除0崩溃、Stack overflow线程栈溢出、Stack overrun栈内存越界、Access violation内存访问违例),然后查看发生异常崩溃的那条汇编指令,从而得到初步的排查方向和线索。接着查看发生异常的那个线程的函数调用堆栈,对照着源代码上下文进行详细的分析。必要时可能要查看调用堆栈中函数中的变量的值,变量值可能是定位问题的关键线索,多次在项目中使用。有时可能还需要查看汇编代码的上下文去辅助分析。
4.1、查看异常类型
打开dump文件,就会显示发生异常的类型,如下所示:
根据显示的异常类型(ExceptionCode值对应的含义,比如0xC0000005对应的就是Access violation内存访问违例)。
通过这个异常类型可以初步判断出异常的种类,比如Access violation(内存访问违例)、Integer divided by zero(除0异常)、Stack overflow(线程栈溢出)等。对于Access violation内存访问违例的异常,原因比较多,很难一步确定引发异常的原因。但对于Integer divided by zero除0异常、Stack overflow线程栈溢出异常,则能给出直接的线索,可以快速地定位问题。
4.2、使用.ecxr命令切换到发生异常的线程上下文,查看发生异常的那条汇编指令
在查看异常类型之后,我们输入.ecxr命令切换到发生异常的线程上下文,查看发生异常的那条汇编指令及相关寄存器的值:
通过查看汇编指令及各寄存器的值,可以初步判断当前发生异常的初步原因,比如可能是访问C++类空指针、野指针或者用户态的代码访问了内核态内存地址。
汇编代码能最直接、最本真的反映出崩溃的原因,程序运行时执行的都是二进制文件中的汇编代码(或者称为二进制机器码,二进制机器码和汇编代码是等价的)。
下面讲两个典型的汇编指令中访问了不该访问的内存地址的异常场景。
4.2.1、汇编指令中访问64KB小地址内存区,引发访问违例,导致崩溃
在Windows系统中,64KB以内的内存地址是禁止访问的,如果程序访问这个范围内的内存,则会触发内存访问违例,系统会强行将进程终止掉。
4.2.2、汇编指令中访问了很大的内核态的内存地址,引发访问违例,导致崩溃
对于32位程序,系统会给进程分配4GB的虚拟内存,一般情况下用户态和内核态会各占一半,即各占2GB,我们编写的代码基本都是运行在用户态的,用户态的代码时不能访问内核态内存地址的(内核态地址是供系统内核模块使用的),如果崩溃指令中访问了一个很大的内存地址,超过用户态的地址范围0-2GB,内存地址大于0x8000000,则会触发内存违例,因为用户态的代码是禁止访问内核态内存地址的。
关于64KB之内的小地址内存区与内核态内存区域,《Windows核心编程》一书中有详细的说明:
此外,了解汇编有很多好处,不仅可以通过查看汇编代码辅助定位软件异常问题,还可以从汇编的角度去理解很多高级语言难以理解的代码执行细节! 关于学习汇编的好处以及如何学习汇编,可以查看我的文章:
C/C++程序员为什么要了解汇编?了解汇编有哪些好处?如何学习汇编?https://blog.csdn.net/chenlycly/article/details/142795872从C++软件调试实战的角度去看多线程编程中的若干细节问题
https://blog.csdn.net/chenlycly/article/details/140742852
4.3、使用kn/kv/kp命令查看异常发生时的函数调用堆栈
接着,使用kn/kv/kp命令(三个命令,可以使用其中任何命令)去查看异常发生时的函数调用堆栈,看看是调用了什么函数触发的异常。根据函数调用堆栈,对照着源码去进行分析。
一般此时没有加载pdb文件,调用堆栈中不会显示具体的函数名和代码的行号:
因为Windbg没有加载包含函数及变量符号信息的pdb文件。要函数调用堆栈中显示具体的函数名和代码行号,则需要拿到pdb文件,然后将pdb文件的路径设置到Windbg中。然后Windbg记载到pdb符号库文件之后,重新输出函数调用堆栈,堆栈中就会显示出具体的函数名和代码行号了。
4.4、使用lm命令查看模块的时间戳,找到对应的pdb文件,设置到Windbg中
函数调用堆栈在没加载pdb文件时,会显示代码所在的模块名称,我们使用lm命令查看这些模块编译生成的时间戳:
然后通过时间戳找来这些模块对应的pdb文件,然后将pdb文件的路径设置到windbg中。如何将pdb文件的路径设置到Windbg中,下面讲实例时会详细说明,此处就不再赘述了。
Windbg加载pdb文件之后,使用kn/kv/kp命令再次输出函数调用堆栈,堆栈中就会显示具体的函数名及行号,这样对照着C++源代码去详细分析引发问题的最终原因了。
有时候为了搞清楚发生异常的本质,我们还需要使用IDA查看相关二进制文件的汇编代码,查看一下发生异常的那条汇编指令的上下文,对照着C++源码,看看那条汇编指令为啥会出现异。
5、实战问题分析实例说明
我们为了方便展开讲解,我们特意使用VisualStudio创建了一个基于MFC对话框的exe测试程序,对话框中有个名为button1的按钮,如下所示:
我们在此按钮的响应中添加了一段引发崩溃的测试代码,故意让程序产生崩溃,测试然后拿到崩溃时的dump文件。
具体的测试代码如下所示:
// 添加的一段测试代码
SHELLEXECUTEINFO *pShExeInfo = NULL;
int nVal = pShExeInfo->cbSize; // 通过空指针访问结构体成员,导致崩溃
CString strTip;
strTip.Format( _T("nVal=%d."), nVal );
AfxMessageBox( strTip );
代码中使用到的结构体SHELLEXECUTEINFO 定义如下:
typedef struct _SHELLEXECUTEINFOW
{
DWORD cbSize; // in, required, sizeof of this structure
ULONG fMask; // in, SEE_MASK_XXX values
HWND hwnd; // in, optional
LPCWSTR lpVerb; // in, optional when unspecified the default verb is choosen
LPCWSTR lpFile; // in, either this value or lpIDList must be specified
LPCWSTR lpParameters; // in, optional
LPCWSTR lpDirectory; // in, optional
int nShow; // in, required
HINSTANCE hInstApp; // out when SEE_MASK_NOCLOSEPROCESS is specified
void *lpIDList; // in, valid when SEE_MASK_IDLIST is specified, PCIDLIST_ABSOLUTE, for use with SEE_MASK_IDLIST & SEE_MASK_INVOKEIDLIST
LPCWSTR lpClass; // in, valid when SEE_MASK_CLASSNAME is specified
HKEY hkeyClass; // in, valid when SEE_MASK_CLASSKEY is specified
DWORD dwHotKey; // in, valid when SEE_MASK_HOTKEY is specified
union
{
HANDLE hIcon; // not used
#if (NTDDI_VERSION >= NTDDI_WIN2K)
HANDLE hMonitor; // in, valid when SEE_MASK_HMONITOR specified
#endif // (NTDDI_VERSION >= NTDDI_WIN2K)
} DUMMYUNIONNAME;
HANDLE hProcess; // out, valid when SEE_MASK_NOCLOSEPROCESS specified
} SHELLEXECUTEINFOW, *LPSHELLEXECUTEINFOW;
#ifdef UNICODE
typedef SHELLEXECUTEINFOW SHELLEXECUTEINFO;
typedef LPSHELLEXECUTEINFOW LPSHELLEXECUTEINFO;
#else
typedef SHELLEXECUTEINFOA SHELLEXECUTEINFO;
typedef LPSHELLEXECUTEINFOA LPSHELLEXECUTEINFO;
#endif // UNICODE
在测试代码中定义了SHELLEXECUTEINFO结构体指针pShExeInfo,并初始化为NULL,然后并没有给该指针赋一个有效的结构体对象地址,然后使用pShExeInfo访问结构体的cbSize成员的内存,因为pShExeInfo中的值为NULL,所以结构体cbSize成员的内存地址是结构体对象起始地址的偏移,因为结构体对象地址为NULL,cbSize成员位于结构体的首位,所以cbSize成员就是结构体对象的首地址,就是NULL,所以就访问64KB小地址内存块的异常,引发内存访问违例,导致程序发生崩溃闪退。
至于如何在程序中设置异常捕获模块去捕获异常、自动生成dump文件,需要在程序中添加异常捕获库。异常捕获库有几个开源方案可供选择,可以使用开源CrashRpt(开源版本有一些缺陷,我们进行了一些优化和改进),也可以使用Google浏览器开源代码中的BreakPad,网上有很多版本,可以去研究一下。
此处通过一个简单的的问题实例详细讲解使用Windbg分析dump文件的完整过程,如果要查看真实项目中的大量实战分析案例,可以查看我的C++软件调试与异常排查从入门到精通的专栏(专栏中包含大量的实战项目分析实例,详细讲解问题的分析过程,很有实战参考价值)
C++软件调试与异常排查从入门到精通专栏介绍与文章汇总https://blog.csdn.net/chenlycly/article/details/125529931
6、使用Windbg详细分析dump文件,展现完整分析过程
6.1、查看异常类型和发生崩溃的汇编指令,初步分析
使用Windbg打开dump文件(直接将dump文件拖入到Windbg),首先我们查看一下发生的异常类型,如下:
然后使用.excr命令切换到发生异常的线程上下文,会自动将发生异常的那条汇编指令显示出来,如下:
我们可以先看一下这条汇编指令以及崩溃时的各个寄存器的值,可能能初步估计出发生异常的原因。如果指令中访问了一个很小的地址或者访问了一个很大的地址,都会触发内存访问违例。从崩溃的这条汇编指令来看,是访问了小地址0x00000000地址,这是访问了小于64KB小地址内存区,这个范围的地址是禁止访问的,所以引发了内存访问违例。这个异常很可能是访问了空指针引起的。
6.2、使用kn/kv/kp命令查看函数调用堆栈
接着输入了kn命令,将函数调用堆栈打印出来:
函数调用堆栈是从下往上看的,最上面一行就是最后调用的一个函数,也是崩溃的那条汇编指令所在的函数。从函数调用堆栈的最后一帧调用的函数来看,程序的崩溃是发生在TestDlg.exe文件模块中,不是其他的dll模块。显示的函数地址是相对TestDlg.exe文件模块起始地址的偏移,为啥看不到模块中具体函数名称呢?那是因为Windbg找不到TestDlg.exe对应的pdb文件,pdb文件中包含对应的二进制文件中的函数名称及变量等信息,Windbg加载到pdb文件才能显示完整的函数名。
查看函数调用堆栈的命令,除了kn,还有kv和kp命令,其中kv还可以看到函数调用堆栈中调用函数时传递的参数,如下所示:
我们需要取来pdb符号库文件,去查看具体的函数名及行号的,这样才好找到直接的线索的。下面就来看看如何获取到TestDlg.exe模块的pdb文件。
6.3、找到pdb文件,设置到windbg中,查看完整的函数调用堆栈
如何才能找到TestDlg.exe文件对应的dpb文件?我们可以通过查看TestDlg.exe文件的时间戳找到文件的编译时间,通过编译时间找到文件对应的pdb文件。在Windbg中输入lm vm TestDlg*命令,可以查看到TestDlg.exe文件的详细信息,其中就包含文件的时间戳:(当前的lm命令中使用m通配符参数,所以在TestDlg后面加上了*号)
可以看到文件是2022年6月25日8点26分23秒生成的,就可以找到对应时间点的pdb文件了。
一般在公司正式的项目中,通过自动化软件编译系统,每天都会自动编译软件版本,并将软件的安装包及相关模块的pdb文件保存到文件服务器中(软件版本放到文件服务器上存放和维护),如下所示:
这样我们就可以根据模块的编译时间找到对应版本的pdb文件了。
我们找到了TestDlg.exe对应的pdb文件TestDlg.pdb,将其所在的路径设置到Windbg中。点击Windbg菜单栏中的File->Symbol File Path...,打开设置pdb文件路径的窗口,将pdb文件的路径设置进去,如下所示:
点击OK按钮之前,最好勾选上Reload选项,这样Windbg就会去自动加载pdb文件了。但有时勾选了该选项,好像不会自动去加载,我们就需要使用.reload /f TestDlg.exe命令去让Windbg强制去加载pdb文件(命令中必须是包含文件后缀的文件全名)。
设置完成后,我们可以再次运行lm vm TestDlg*命令去看看pdb文件有没有加载进来:
如果已经加载进来,则会在上图中的位置显示出已经加载进来的pdb文件的完整路径,如上所示。
关于pdb符号库文件的详细说明,可以查看我之前写的文章:
pdb符号库文件详解https://blog.csdn.net/chenlycly/article/details/125508858加载到TestDlg.exe文件对应的pdb文件之后,我们再次执行kn命令就可以包含具体的函数名及及代码的行号信息了,如下:
我们看到了具体的函数名CTestDlgDlg::OnBnClickedButton1,还看到了对应的代码行号312。通过这些信息,我们就能到源代码中找到对应的位置了,如下所示:
是访问了空指针产生的异常。当然上面的代码是我们故意这样写的,目的是为了构造一个异常来详细讲解如何使用Windbg进行动态调试跟踪的。
6.4、可以将C++源代码路径设置到Windbg中,Windbg会自动跳转到源代码行号上
为了方便查看,我们可以直接在Windbg中设置C++源码路径,这样Windbg会自动跳转到源码对应的位置。点击Windbg菜单栏的File->Source File Path...,将源码路径设置进去:
然后在Windbg点击函数调用堆栈中的每一行记录前面的数字超链接,会自动跳转到对应的函数及行号上,如下所示:
上图中的函数调用堆栈中很多模块是系统库中的,比如mfc100u、User32等,这些库是系统库,是没有源码的。我们可以点击最下面的第23个链接,其位于我们应用程序的模块中,会自动跳转到对应的代码中,如下:
6.5、有时需要查看函数调用堆栈中函数的局部变量或C++类对象中变量的值
有时我们通过查看变量的值,找到排查问题的线索,比如变量中值为0或者很大的异常值。这点我们在多次问题排查中使用到,确实能找到一些线索。可以查看函数中局部变量的值,也可以查看函数所在类对象的this指针指向的类对象中变量的值。我们要查看哪个函数,就点击函数调用堆栈中每一行前面的数字超链接,如下所示:
我们看到了局部变量pShExeInfo 的值:
struct _SHELLEXECUTEINFOW * pShExeInfo = 0x00000000
我们可以点击this对象的超链接:
就能查看当前函数对应的C++类对象中成员变量的值,如下:
有时函数中相关变量的值,对于分析当前的C++软件异常,可能是关键线索,比如我之前写过的两篇项目问题排查实例文章:
通过查看Windbg中的变量值去定位C++软件异常问题https://blog.csdn.net/chenlycly/article/details/125731044通过查看Windbg中变量值去定位C++软件异常的又一典型案例分享
https://blog.csdn.net/chenlycly/article/details/125793532通过查看Windbg中汇编指令及内存中的值去定位软件崩溃问题
https://blog.csdn.net/chenlycly/article/details/127033741但有时不一定能查看变量的值,因为当前通过异常捕获模块自动生成的dump文件一般是minidump文件,文件也就几MB左右,不可能包含所有变量的值。所以要在minidump文件中查看变量的值,要看运气的,有时能查看到,有时是看不到的。这里要讲一下dump文件的分类,主要分为minidump文件和全dump文件。
关于dump文件的分类与dump文件的生成方式,可以查看我之前写的文章:
dump文件类型与dump文件生成方法详解https://blog.csdn.net/chenlycly/article/details/127991002
6.6、有时可能需要使用IDA去查看二进制文件的汇编代码上下文去辅助分析
有时通过函数调用堆栈和源码很难定位问题时,可能需要使用IDA打开二进制文件去查看汇编代码的上下文去辅助定位问题。关于如何使用IDA查看汇编代码去辅助排查问题,可以参见我之前写的文章:
使用IDA查看汇编代码上下文去辅助排查C++软件异常问题https://blog.csdn.net/chenlycly/article/details/128942626
7、最后
本文详细讲述了使用Windbg分析dump文件的一般步骤与诸多细节,并给出了一个实战分析实例,有一定的实战参考价值。