最近遇到发布的动态库在公司win 7 x86机器上测试没有问题,但是在客户的机器上会出现崩溃,于是研究了一下调试方法。
参考
https://blog.csdn.net/lk142500/article/details/80563552
一、产生dump文件
编写测试demo, 调用我们的动态库,在测试代码中增加CCreateDump类
头文件
#pragma once
#include<string>
using namespace std;
class CCreateDump
{
public:
CCreateDump();
~CCreateDump();
static CCreateDump* Instance();
static long __stdcall UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo);
void DeclarDumpFile(std::string dmpFileName = "");
private:
static std::string strDumpFile;
static CCreateDump* __instance;
};
.cpp文件
#include "CreateDump.h"
#include <Windows.h>
#include "CreateDump.h"
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")
CCreateDump* CCreateDump::__instance = NULL;
std::string CCreateDump::strDumpFile = "";
CCreateDump::CCreateDump()
{
}
CCreateDump::~CCreateDump()
{
}
long CCreateDump::UnhandleExceptionFilter(_EXCEPTION_POINTERS* ExceptionInfo)
{
HANDLE hFile = CreateFile("dumpfile.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// HANDLE hFile = CreateFile(strDumpFile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
printf("ok\n");
if (hFile != INVALID_HANDLE_VALUE)
{
printf("error\n");
MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = ExceptionInfo;
ExInfo.ClientPointers = FALSE;
// write the dump
BOOL bOK = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);
CloseHandle(hFile);
if (!bOK)
{
DWORD dw = GetLastError();
//写dump文件出错处理,异常交给windows处理
printf("write file error\n");
return EXCEPTION_CONTINUE_SEARCH;
}
else
{ //在异常处结束
return EXCEPTION_EXECUTE_HANDLER;
}
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
}
void CCreateDump::DeclarDumpFile(std::string dmpFileName)
{
SYSTEMTIME syt;
GetLocalTime(&syt);
char c[MAX_PATH];
sprintf_s(c, MAX_PATH, "[%04d-%02d-%02d %02d:%02d:%02d]", syt.wYear, syt.wMonth, syt.wDay, syt.wHour, syt.wMinute, syt.wSecond);
strDumpFile = std::string(c);
if (!dmpFileName.empty())
{
strDumpFile += dmpFileName;
}
strDumpFile += std::string(".dmp");
SetUnhandledExceptionFilter(UnhandleExceptionFilter);
}
CCreateDump* CCreateDump::Instance()
{
if (__instance == NULL)
{
__instance = new CCreateDump;
}
return __instance;
}
测试代码
void mycall()
{
printf("1\n");
int *p = NULL;
*p = 5;
}
int main(int argc, char *argv[]) {
CCreateDump::Instance()->DeclarDumpFile("dumpfile");
mycall();
}
编译出debug版本的sample在客户机器上运行,并让客户在某个位置运行sample, 比如d:\Debug_Win32文件夹。
查看分析dumpfile文件
同时保存所有动态库和exe对应的pdb文件。
最终客户会产生一个dumpfile文件。将该文件放在开发机器的d:\Debug_Win32目录下,同时将原先的dll,pcb,exe文件都放在该目录下,使用vs2013或以上版本打开。选择使用仅限本机进行调试。就可以看到对应的堆栈调用信息了。
如果客户的机器邮寄到公司,可以有两种选择
1)通过网络共享的方式访问客户机器的d:\Debug_Win32的目录,然后在安装有vs2013的机器上双击dumpfile文件
2)可以在客户的机器上安装vs2013或以上版本。