推荐一种程序崩溃闪退或卡死的分析方法
<p>在实际开发中,经常遇到程序崩溃闪退或者卡死的问题,在遇到这种问题的时候,往往很难捕捉异常,且日志也无法正确记录到问题发生的位置。在Windows操作系统中,dump文件就可以记录并保存程序崩溃时的快照,今天我们通过一个小例子,简述一种生成dump文件的方法,仅供学习分享使用,如有不足之处,还请指正。</p><p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250611004456493-1748932328.png"></p>
<p> </p>
<h1>闪退场景</h1>
<p> </p>
<p>在下面例子中,我们有一个WinForm程序,在FormMain的构造方法中,制造一个除零异常,此异常会导致程序闪退,如下所示:</p>
<pre class="language-csharp highlighter-hljs"><code>namespace TestDump
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
//抛出一个异常
throw new DivideByZeroException();
}
}
}</code></pre>
<p>在我们启动程序时,双击软件,然后发现程序“转了几圈,就消失了”,程序并没有启动起来。</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250610223739438-733998913.gif"></p>
<p>当然,上述只是我们的一个小例子,实际工作中,我们并不会制造这么愚蠢的异常出来。</p>
<p> </p>
<h1>异常分类</h1>
<p> </p>
<p>根据异常发生和处理的机制不同,主要分为如下两类:</p>
<p>托管异常:托管异常是由 .NET 运行时管理的异常,它们通常在托管代码中抛出并处理。例如,在 C# 中使用 <code class="dqa-code-span">try-catch</code> 块捕获的异常就是托管异常。这些异常通常由 .NET 的类库抛出,例如 <code class="dqa-code-span">ArgumentNullException</code>, <code class="dqa-code-span">IndexOutOfRangeException</code> 等。</p>
<p>非托管异常:非托管异常是由操作系统或其他非 .NET 代码(如调用本地库或使用 P/Invoke 调用 Windows API)抛出的异常。这些异常不是由 .NET 运行时直接管理的,因此需要使用特定的技术来捕获和处理。</p>
<p>在实际应用中,托管异常容易识别和处理;非托管异常通常需要结合使用托管和原生代码的技术来处理。</p>
<p> </p>
<h1>什么是dump文件?</h1>
<p> </p>
<p>Dump文件是一种包含了程序运行时的内存、寄存器状态、堆栈跟踪等信息的文件,通常用于调试和故障排查。当程序崩溃或发生异常时,操作系统或程序自身可能会生成一个Dump文件,以便开发者或技术支持人员能够分析程序崩溃的原因,并采取相应的修复措施。</p>
<p>Dump文件通常包含以下信息:</p>
<ul>
<li>程序的内存映像:即程序在崩溃时内存中的数据和代码的状态。</li>
<li>寄存器状态:包括CPU的寄存器在崩溃时的值,这些值对于理解程序崩溃时的上下文非常关键。</li>
<li>堆栈跟踪:记录了程序崩溃时执行的函数调用序列,有助于确定程序崩溃的具体位置。</li>
</ul>
<p data-pid="ljnXTgYb">不同的操作系统和程序可能会生成不同格式的Dump文件。例如,在Windows操作系统中,应用程序崩溃时可能会生成`.dmp`文件,而在Linux系统中,则可能会生成`core`文件。开发者或技术支持人员可以使用专门的调试工具来打开和分析这些Dump文件,以便找到并修复导致程序崩溃的问题。</p>
<p data-pid="ljnXTgYb"> </p>
<h1>生成dump文件</h1>
<p> </p>
<p>在 Windows 操作系统中,可以将 Windows 错误报告 (WER) 配置为在应用程序崩溃时生成转储。具体步骤如下:</p>
<p>在Windows左下角搜索框输入“regedit”打开注册表编辑器,如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250610232323015-1937886752.png"></p>
<p>在注册表中,依次打开“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps”,然后创建三个字段,如下所示:</p>
<ul>
<li>DumpFolder:表示Dump生成的目录,此值的类型为REG_EXPAND_SZ(可扩充字符串)。</li>
<li>DumpCount:表示最多生成dump文件的数量。此值为DWORD的32位整数,默认设置为10</li>
<li>DumpType:生成的Dump文件类型:0:自定义类型,1:MiniDump,2:Full Dump。此值为DWORD的32位整数</li>
</ul>
<p>具体如下图所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250610233524683-235493697.png"></p>
<p>注册表也可以通过以下命令创建:</p>
<pre class="language-powershell highlighter-hljs"><code>reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps"
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpFolder /t REG_EXPAND_SZ /d "C:\mydumps" /f
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpType /t REG_DWORD /d 2 /f
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /v DumpCount /t REG_DWORD /d 10 /f
pause</code></pre>
<p>复制上述命令,保存在一个后缀为.bat的文件中,然后双击即可。如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250610235308766-27109332.png"></p>
<p> </p>
<h1>分析dump文件</h1>
<p> </p>
<p>通过上述步骤,当程序发生崩溃时,就会在指定的目录生成dump文件,如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250611000945044-1525340097.png"></p>
<p>如果就简单的.net程序闪退生成的dump文件,可以在Visual Studio 2022中打开dump文件,然后点击“运行诊断分析”,如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250611001302019-1645217483.png"></p>
<p>Visual Studio 2022会自动定位到发生闪退的异常所在位置,如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250611001516819-211557964.png"></p>
<p>在“诊断分析”页面,点击“分析”,可以查看分析结果,然后点击结果,即可看到分析摘要中显示的具体异常信息。</p>
<p><img src="https://img2024.cnblogs.com/blog/1068941/202506/1068941-20250611001627398-666034609.png"></p>
<p>当然上述分析只是针对相对简单的崩溃异常分析,如果复杂的闪退场景,则需要借助专业的调试工具,如WinDbg等,本文暂不讨论。</p>
<p>以上就是《推荐一种程序崩溃闪退或卡死的分析方法》的全部内容,旨在抛砖引玉,一起学习,共同进步。</p>
</div>
<div id="MySignature" role="contentinfo">
<div id="AllanboltSignature">
<p style="border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 30px; font-family: 微软雅黑; font-size: 12px" id="PSignature">
<br>
<img alt="" src="https://images.cnblogs.com/cnblogs_com/hsiang/1154298/o_115f1cd8.jpg" width="80px" height="80px">
作者:老码识途
<br>
出处:http://www.cnblogs.com/hsiang/
<br>
本文版权归作者和博客园共有,写文不易,支持原创,欢迎转载【点赞】,转载请保留此段声明,且在文章页面明显位置给出原文连接,谢谢。
<br>关注个人公众号,定时同步更新技术及职场文章
<br><br>
</p>
</div><br><br>
来源:https://www.cnblogs.com/hsiang/p/18923030
頁:
[1]