1. 如何排查程序crash,freeze等问题?

在日常开发中,即使代码写得有多谨慎,免不了还是会发生各种意外的事件,比如服务器内存突然飙高,又或者发生内存溢出(OOM)。当发生这种情况时,我们怎么去排查,怎么去分析原因呢?

最快的解决方式是生成dump文件,通过生成dump文件使用调试工具进行调试,还原程序崩溃时的状态,能够起到快速定位排查问题的作用。

Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。Dump文件是用来给驱动程序编写人员调试驱动程序用的,这种文件必须用专用工具软件打开,比如使用WinDbg、VS,Jprofiler打开。

 

2. 什么是dump file?

Windows下Dump文件分为两大类,内核模式Dump和用户模式Dump。内核模式Dump是操作系统创建的崩溃转储,最经典的就是系统蓝屏,这时候会自动创建内核模式的Dump。用户模式Dump进一步可以分为完整Dump(Full Dump)和迷你Dump(Minidump)。完整Dump包含了某个进程完整的地址空间数据,以及许多用于调试的信息,而Minidump则有许多类型,根据需要可以包含不同的信息,有的可能只包含某个线程和部分模块的信息。在程序开发过程中出现的应用崩溃属于用户模式Dump。因此,要弄清楚这种Dump文件的组成、生成方式、作用。

 

3. Dump文件的作用 

Dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中。主要是用来在系统中出现异常或者崩溃的时候来生成dump文件,然后用调试器进行调试,这样就可以把生产环境中的dmp文件拷贝到自己的开发机上,调试就可以找到程序出错的位置。
在C++编程实践中,通常都会遇到内存访问无效、无效对象、堆栈溢出、空指针调用等常见的C/C++问题,而这些问题最后常会导致:系统崩溃。为解决崩溃问题常用的手段一个就是生成dump文件进行代码调试,另外一个就是使用远程调试remote debugger进行调试。但remote debugger在要求程序源代码和可执行文件在同一个局域网内,对环境的要求较高。因此对于程序崩溃较好的解决方式便是生成dump文件进行解析,快速定位到程序崩溃位置,对问题进行排查。

 

4. 如何生成dump文件

4.1 主动生成dump file

首先要查找运行的Java程序的pid

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YWo5qCI5byA5Y-R5LiO5rWL6K-V,size_20,color_FFFFFF,t_70,g_se,x_16

然后使用jmap命令生成dump文件。

file后面是保存的文件名称,1246则是java程序的PID。 

jmap -dump:format=b,file=user.dump 39830
Last login: Wed Feb 16 09:37:19 on ttys000
yuhyan@YUHYAN-M-W5NE ~ % jmap -dump:format=b,file=user.dump 39830
Exception in thread "main" java.io.IOException: No such process
	at jdk.attach/sun.tools.attach.VirtualMachineImpl.sendQuitTo(Native Method)
	at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:94)
	at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:58)
	at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
	at jdk.jcmd/sun.tools.jmap.JMap.executeCommandForPid(JMap.java:128)
	at jdk.jcmd/sun.tools.jmap.JMap.dump(JMap.java:248)
	at jdk.jcmd/sun.tools.jmap.JMap.main(JMap.java:114)

 

 4.2 通过使用任务管理器生成

注: 使用任务管理器生成转储文件需要遵循一个原则:用32位任务管理器给32位进程(无论该进程是运行在32位还是64位系统上面)生成转储文件,用64位任务管理器给64位进程生成转储文件。在64位系统上。

  1. 32位的任务管理器位于C:WindowsSysWOW64 askmgr.exe
  2. 默认打开的任务管理器是64位。

在程序崩溃后,先不关闭程序,在任务管理器中找到该程序对应的进程。右键—>创建转储文件

20170804102834649

 此时会在默认的目录下创建出一个dump文件

20170804102935686 

  

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YWo5qCI5byA5Y-R5LiO5rWL6K-V,size_20,color_FFFFFF,t_70,g_se,x_16

4.3 修改注册表

1) Win + R 输入regedit打开注册表

2)找到注册表路径:

HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsWindowsError ReportingLocalDumps

3)在右边窗口新建->字符串值 DumpCount,DumpFolder,DumpType 并修改其值,如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YWo5qCI5byA5Y-R5LiO5rWL6K-V,size_20,color_FFFFFF,t_70,g_se,x_16

这样系统在程序崩溃时就会在C:CrashDump 文件夹下生成对应程序的dump文件。在实际工作中,我们可以将这些操作写成一个脚本文件,一键完成。

对上面DumpType解释:

0 = Create a custom dump
1 = Mini dump
2 = Full dump
 

如何查看和调试dump文件?

 

5.1 调试Dump文件

5.1.1.VS调试

用VS打开dmp文件。测试时 dmp文件时本地产生的,因此VS会依据dmp文件自行找到exe,pdb和源代码的路径。因此直接点击调试,程序会出错代码行中断。

20170804103638920

20170804103712436

 

但若dmp文件是exe在另一台机器上产生的,则我们最好把exe,pdb,dmp放到同一文件夹下,必须保证pdb与出问题的exe是同一时间生成的,用VS打开dmp文件后还需要设置符号表文件路径和源代码路径:

(1)  当把pdb文件与dmp文件放入同一目录下时,就不需设置其路径,否则需要设置

工具->选项->调试->符号:

20170804103750964

 

(2)还需设置源代码路径:

属性->调试源代码:

20170804103805866

 

这样点击“使用仅限本机进行调试”,即可在出错代码行中断:

20170804103835109

 

5.1.2 WinDbg调试

(1)设置pdb路径:File ->Symbol File Path

20170804103907460

(2)设置exe路径:File -> Image File Path

20170804103925399

 

(3)设置源代码路径:File -> Source File Path(指sln所在目录)

20170804103940506

 

(4)打开dmp文件:File ->Open Crash Dump

(5)执行命令 !analyze –v

20170804104002984

20170804104011162

参考:https://blog.csdn.net/zhaihaibo168/article/details/103706585

icandoit2010的专栏_wufeng_asia_CSDN博客-c/c++,linux,杂谈领域博主

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐