windows server dump文件
1. mini dump:
***** 需要包含 dbghelp.dll 库
****mini_dump.h文件:
// reference:https://msdn.microsoft.com/zh-cn/library/windows/desktop/ee416349(v=vs.85).aspx
#ifndef mini_dump_h__
#define mini_dump_h__
namespace minidump
{
void MiniDumpBegin(const char* app_name, const char* app_version);
}
#endif // mini_dump_h__
mini_dump.cpp文件:
#include "mini_dump.h"
#include <windows.h>
#include <shellapi.h>
#include <string>
// Is dbghelp.h dbghelp.lib dbghelp.dll windows build-in?
#include <dbghelp.h>
#pragma comment (lib,"dbghelp.lib")
// Visual Studio 2005 compatible
#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
namespace minidump
{
// needn't delete
std::string* app_name = 0;
std::string* app_version = 0;
// "c:\folder1\xxx.exe" to "c:\folder1\"
std::string GetDirectory(const std::string& execution)
{
std::string path("");
size_t pos = execution.find_last_of("\\");
if (pos != std::string::npos)
path = execution.substr(0, pos + 1);
return path;
}
// Generage dump file to avoid file name collisions
std::string GetDumpFileMark()
{
SYSTEMTIME system_local_time;
GetLocalTime(&system_local_time);
char file_name[MAX_PATH];
snprintf(file_name, MAX_PATH, "%s%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
app_name->c_str(), app_version->c_str(),
system_local_time.wYear, system_local_time.wMonth, system_local_time.wDay,
system_local_time.wHour, system_local_time.wMinute, system_local_time.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
return file_name;
}
// Generate dump file whole name in GetModuleFileName()'s directory
// Like: F:\reference\project\TestMiniDump\VsProject\build\Debug\dump\20161015-110026-8552-9344.dmp
std::string GetDumpFileName()
{
char file_path[MAX_PATH];
GetModuleFileName(NULL, file_path, MAX_PATH);
std::string path = GetDirectory(file_path);
path += "dump\\";
std::string file_mark = GetDumpFileMark();
path += file_mark;
return path;
}
MINIDUMP_EXCEPTION_INFORMATION GetExpParam(EXCEPTION_POINTERS* exception_pointers)
{
MINIDUMP_EXCEPTION_INFORMATION exp_param;
exp_param.ThreadId = GetCurrentThreadId();
exp_param.ExceptionPointers = exception_pointers;
exp_param.ClientPointers = TRUE;
return exp_param;
}
int GenerateDump(EXCEPTION_POINTERS* exception_pointers)
{
std::string dump_file_name = GetDumpFileName();
// The "\dump" whole directory
std::string dump_file_dir = GetDirectory(dump_file_name);
CreateDirectory(dump_file_dir.c_str(), NULL);
HANDLE dump_file_handle = CreateFile(dump_file_name.c_str(),
GENERIC_READ| GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ,
0, CREATE_ALWAYS, 0, 0);
MINIDUMP_EXCEPTION_INFORMATION exp_param =
GetExpParam(exception_pointers);
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
dump_file_handle, MiniDumpNormal, &exp_param, NULL, NULL);
return 0;
}
LONG _stdcall GolbalExceptionHandler(EXCEPTION_POINTERS* exception_pointers)
{
GenerateDump(exception_pointers);
return EXCEPTION_EXECUTE_HANDLER;
}
void IntiializeMemory()
{
app_name = new std::string();
app_version = new std::string();
}
void MiniDumpBegin(const char* app_name, const char* app_version)
{
IntiializeMemory();
*minidump::app_name = app_name;
*minidump::app_version = app_version;
SetUnhandledExceptionFilter(GolbalExceptionHandler);
}
}
使用方法,在main函数开始出,调用:MiniDumpBegin函数,如图:
2. 使用注册表:
opendump.bat文件:----写注册表
@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
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. 去打开服务
程序出现崩溃,C:\ 会出现:
CrashDump 文件
3. 调试dump文件 参考链接https://blog.csdn.net/tojohnonly/article/details/72864694
打开 Dump 文件
双击打开生成的 Dump 文件 , 会默认用 VS2012 打开并自动创建一个解决方案 , Dump 摘要信息如下 :
一定要确保 进程名称
对应的程序路径在本地存在 , 同时确保最初生成程序的对应 .pdb
符号文件也在当前目录 ;
有时从客户那里反馈回来的 Dump 文件程序路径和本地的不一致 , 需要将程序拷贝到 Dump 信息里面的路径中去 ;
设置 Symbols 路径
调试文件需要对应的符号文件 , 我们需要设置符号文件对应的路径 :
在 Dump 信息摘要右上角 , 点击 设置符号路径
:
推荐使用 Microsoft 符号服务器
, 但第一次在线下载会有点慢 ; 当然也可以自己下载符号集文件到某个路径 , 再讲符号路径指向该路径 :
设置源码路径
在左侧的解决方案处右键点击 属性
-> 调试源文件
, 将源代码的路径添加进来 , 注意一定是解决方案所在的路径(sln) :
调试 Dump 文件
准备工作已就绪 , 现在在 Dump 文件摘要右上角点击 使用 仅限本机 进行调试
:
如果提示
无法找到调试信息 , 或者调试信息不匹配 , 无法查找或打开 PDB 文件
, 说明没有将最初生成程序的对应.pdb
符号文件放在调试程序所在的目录 , 或者.pdb
符号文件与当前的程序版本不匹配 ;
程序会重现当时崩溃前的调用堆栈 , 如下图所示 :
可以看出程序已经定位到了崩溃前的那一行代码 , 非常方便排查 ;
4. 使用完成后,还原注册表,运行closedump.bat文件。
5. 删除 C盘下的 CrashDump 文件。
与minidump 相关知识点:
通过 /Eha 编译参数,我们可以既捕获C++异常,又捕获结构化异常。
通过 _set_se_tranlator 可以把结构化异常转换成C++异常,并保存异常发生的现场(需要 /Eha 参数)。
通过 SetUnhandledExceptionFilter,可以捕获没有 try-catch/__try __except 保护的线程上抛出的异常。
通过 MiniDumpWriteDump 加上我们保存的异常现场信息,我们可以在生成 mini dump 时把 进程id、线程id、发生异常的时间、ContextRecord 都写进 mini dump(前三项通过文件名的形式),极大的方便后期调试。
参考原文:https://www.cnblogs.com/yangchaobj/archive/2013/02/23/2923479.html
标准c++异常:try catch
vc异常:try except
如果在vs 编译器里混用,需要要打开/EHsc开关。
windows 结构化异常 使用的是 try except,如果模拟C++ 异常,参考下面代码,
/ crt_settrans.cpp
// compile with: /EHa
#include <stdio.h>
#include <windows.h>
#include <eh.h>
void SEFunc();
void trans_func( unsigned int, EXCEPTION_POINTERS* );
class SE_Exception
{
private:
unsigned int nSE;
public:
SE_Exception() {}
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
int main( void )
{
try
{
_set_se_translator( trans_func );
SEFunc();
}
catch( SE_Exception e )
{
printf( "Caught a __try exception with SE_Exception./n" );
}
}
void SEFunc()
{
__try
{
int x, y=0;
x = 5 / y;
}
__finally
{
printf( "In finally/n" );
}
}
void trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )
{
printf( "In trans_func./n" );
throw SE_Exception();
}
参考原文:https://blog.csdn.net/wallaceli1981/article/details/6162125