目录
一、前言
1. 什么是 core dump
Coredump叫做核心转储,它是进程运行时在突然崩溃的那一刻的一个内存快照。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个文件里。
该文件也是二进制文件,可以使用gdb、elfdump、objdump或者windows下的windebug、solaris下的mdb进行打开分析里面的具体内容。
注:core是在半导体作为内存材料前的线圈,当时用线圈当做内存材料,线圈叫做core。用线圈做的内存叫做core memory。
2. 无法生成 dmp 文件
虽然我们知道进程在coredump的时候会产生core文件,但是有时候却发现进程虽然core了,但是我们却找不到core文件
可以将 dmp 文件的大小,调高
二、创建 dmp 方法
1. 修改注册表 当程序崩溃时 产生崩溃转储文件(dmp)
以管理员身份 运行 :OpenDump.bat 其本质是写注册表。
运行后: 任何程序崩溃都会在C:\CrashDump 产生dmp文件(比较大,约50到200M)。
至少在Win7、Win10的电脑,Win10的平板上运行正确。
a) OpenDump.bat - 自动生成dmp文件
@echo off
echo 正在启用Dump...
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:\CrashDump" /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
echo Dump已经启用
pause
@echo on
b) 注册表 参数说明:
Value | 描述 | Type | 默认值 |
DumpFolder | 文件保存路径 | REG_EXPAND_SZ |
%LOCALAPPDATA%CrashDumps |
DumpCount | dump文件的最大数目 |
REG_DWORD | 10 【注 超过最大值时,将最早的 dmp 文件删除】 |
DumpType | 指定生成的dump类型: |
REG_DWORD | 1 |
CustomDumpFlags | 仅在DumpType为0时使用 |
REG_DWORD | MiniDumpWithDataSegs | MiniDumpWithUnloadedModules | MiniDumpWithProcessThreadData |
c) CloseDump.bat - 关闭此功能
@echo off
echo 正在关闭Dump...
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps" /f
echo Dump已经关闭
pause
@echo on
2. 在程序中加入代码
程序中加入存储Dump的代码
通过SetUnhandledExceptionFilter设置捕获dump的入口,然后通过MiniDumpWriteDump生成dump文件
#include<windows.h>
#include<DbgHelp.h>
#include "createdump.h"
// 处理Unhandled Exception的回调函数
LONG WINAPI GPTUnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
{
CreateMiniDump(pExceptionInfo, L"Exception.dmp");
exit(pExceptionInfo->ExceptionRecord->ExceptionCode);
return EXCEPTION_EXECUTE_HANDLER; // 程序停止运行
}
void fun(int *p)
{
p[0]=0;
}
int main(int argc, char * argv[])
{
//注册异常处理函数
SetUnhandledExceptionFilter(GPTUnhandledExceptionFilter);
fun(NULL);
return 0;
}
"createdump.h"
#pragma once
#include <windows.h>
#include <imagehlp.h>
#include <stdlib.h>
#pragma comment(lib, "dbghelp.lib")
inline BOOL IsDataSectionNeeded(const WCHAR* pModuleName)
{
if (pModuleName == 0)
{
return FALSE;
}
WCHAR szFileName[_MAX_FNAME] = L"";
_wsplitpath(pModuleName, NULL, NULL, szFileName, NULL);
if (wcsicmp(szFileName, L"ntdll") == 0)
{
return TRUE;
}
return FALSE;
}
inline BOOL CALLBACK MiniDumpCallback(PVOID pParam, const PMINIDUMP_CALLBACK_INPUT pInput, PMINIDUMP_CALLBACK_OUTPUT pOutput)
{
if (pInput == 0 || pOutput == 0)
return FALSE;
switch (pInput->CallbackType)
{
case ModuleCallback:
if (pOutput->ModuleWriteFlags & ModuleWriteDataSeg)
if (!IsDataSectionNeeded(pInput->Module.FullPath))
pOutput->ModuleWriteFlags &= (~ModuleWriteDataSeg);
case IncludeModuleCallback:
case IncludeThreadCallback:
case ThreadCallback:
case ThreadExCallback:
return T