前言
之前分享过几篇调试的文章,在那几篇文章里,我主要是在分析转储文件(也叫 dump
文件,或简称 dump
),而不是实时调试
。通常,程序发布后,我们很难有机会做实时调试
。我们做的最多的是事后调试
。能否抓到有效的转储文件对我们分析问题至关重要。
你知道什么是转储文件吗?
你知道什么时候应该抓取转储文件吗?
你抓取过转储文件吗?
你知道怎么抓取转储文件吗?
你知道几种抓取转储的方法呢?
如果你对以上问题感兴趣,那么请继续阅读吧。
约定:
后续文章中提到 dump
时,既可能是动词,也可能是名词,需要根据语境区分。用作动词时,表示抓取转储文件
。比如,dump某个进程
表示抓取某个进程的转储文件。用作名词时,表示转储文件。比如,分析 dump
表示分析转储文件。
什么是转储文件
转储文件是什么?我们可以这样简单的理解: 转储文件是进程某一时刻的快照。更准确的解释,请参考微软官方的介绍,摘录如下:
What is a dump file?
A dump file is a snapshot of an app at the point in time the dump is taken. It shows what process was executing and what modules were loaded. If the dump was saved with heap information, the dump file contains a snapshot of what was in the app's memory at that point in time. Opening a dump file with a heap in Visual Studio is like stopping at a breakpoint in a debug session. Although you cannot continue execution, you can examine the stacks, threads, and variable values of the app at the time the dump occurred.
中文版(感谢谷歌翻译,我做了调整):
转储文件是应用程序在进行转储那一时刻的快照。 它显示了正在执行的进程以及已加载的模块。如果转储时保存了堆信息,则转储文件将包含该时间点应用程序的内存快照。 在 Visual Studio 中打开包含堆信息的转储文件就像调试会话中的在断点处停止一样。 尽管无法继续执行,但是可以查看应用程序在发生转储时的堆栈,线程和变量值。
从以上描述中我们了解到:
- 转储文件是进程在某一时刻的快照,可以包含
模块
,堆
,栈
等信息。 - 调试转储文件的时候,我们无法像调试程序那样让程序运行起来。不能使用
单步执行
,设置断点
等功能。 - 虽然无法让程序运行起来,但是我们依然可以查看
线程
,调用栈
,堆
,变量
等信息。
悄悄告诉你:
我刚开始连转储文件是什么都不知道,更不会抓取转储文件了。在分析第一个转储文件的时候,我甚至还想单步调试下。哈哈~
什么时候需要转储文件?
当我们程序发布后,出现崩溃
,死锁
,功能异常
等情况的时候,我们需要调试分析。以下几种情况,不太适合实时调试
。最好可以在出问题的时候抓取 转储文件,供我们事后分析
。
- 程序在客户机器上出问题了,但是限于条件,我们不能在客户机器上调试。
- 某个
bug
很难重现,有时候运行几天后才会出现,我们需要在问题出现的时候保存相关信息。 - 我们发布的是服务器端的程序。程序故障后,我们需要尽快恢复服务,不能长时间让服务进程处于 “宕机” 状态。
下面这段关于 转储文件用途的介绍,同样摘自微软官方。
Dumps are primarily used for debugging issues that occur on machines that the developer doesn’t have access to. For example, you can use a dump file from a customer's machine when you can’t reproduce the customer's crash or hang on your machine. Dumps are also created by testers to save crash or hang data so that the test machine can be used for more testing. The Visual Studio debugger can save dump files for managed or native code. The debugger can load dump files that were created by Visual Studio or by other programs that save files in the minidump format.
中文版(感谢谷歌翻译,我做了调整):
转储主要用于调试 开发人员无法访问的计算机上发生的问题。 例如,当您无法在自己机器上重现客户遇到的崩溃或挂起时,可以使用客户计算机上保存的转储文件。测试人员也可以创建转储文件以保存崩溃或挂起数据,以便继续做更多的测试。Visual Studio 可以为托管代码或本机代码保存转储文件。调试器可以加载由 Visual Studio 或其他程序以 minidump 格式保存的转储文件。
如何抓取转储文件
在对转储文件有个初步了解后,我们还需要知道如何抓取转储文件。我把需要抓取转储文件的情形分为以下四大类,每种情形有对应的抓取方法:
在任意时刻抓取
dump
,不必等待进程出现异常后再抓取。有时候我们想知道进程在某一时刻的状态(比如,程序不响应了),我们可以抓个
dump
分析下原因。系统中的进程异常退出时,自动生成转储文件。
有时候,进程莫名其妙退出了,我们想分析下原因。这时候可以做些设置,让进程异常退出的时候能留下一份转储文件(或者中断到调试器)。这样就可以进一步分析原因了。
自己的进程异常后,自动保存转储文件供我们事后分析。
我们自己的进程出现异常的时候,如果能自动保存一份转储文件,并保存一些关键信息(例如,日志,异常退出时的截屏等)供我们事后分析该多好啊。当然可以。很多软件都有类似的机制,比如
QQ
,微信
,firefox
等。我们当然也想为我们自己的程序增加类似的功能,对吧?抓取系统级别的转储文件。
有时候,我们需要抓取一个系统级的转储文件。比如,想知道某个跨进程的
COM
调用卡在哪里了。了解如何抓取系统级的转储文件也很有必要,说不定在关键时刻能帮上我们的大忙。
本想在一篇文章中介绍一下每种情形的抓取方法,结果发现越写越多,每种情形都可以独立成篇。如果写在一起,真的太太太长了。所以我决定针对每种情形专门写一篇文章做简单介绍。请期待后续文章!
总结
- 转储文件是进程在某一时刻的快照。
- 转储文件中可以包含
模块
,堆
,栈
,线程
等信息。 - 调试转储文件时,不能执行单步,设置断点等操作。
- 调试转储文件是事后调试的重要手段。
- 转储文件在很多情境下都很有用,学会抓取转储文件有助于我们调试问题。