C++ 崩溃转储生成和分析问题
我使用了来自的示例,并在我的应用程序中使用了相同的示例。最近,对于应用程序中的实际崩溃,堆栈跟踪有点无用 另一个问题是生成的dmp文件模块版本不匹配。我已经仔细检查了模块版本,它是相同的,但是转储文件有不同的版本。文件版本为2.8.0.4,dmp文件版本为2.08.0.4 我研究了一些关于stackoverflow的答案,不了解我缺少哪些功能。 KB链接不再存在- 我的实现C++ 崩溃转储生成和分析问题,c++,winapi,crash-dumps,C++,Winapi,Crash Dumps,我使用了来自的示例,并在我的应用程序中使用了相同的示例。最近,对于应用程序中的实际崩溃,堆栈跟踪有点无用 另一个问题是生成的dmp文件模块版本不匹配。我已经仔细检查了模块版本,它是相同的,但是转储文件有不同的版本。文件版本为2.8.0.4,dmp文件版本为2.08.0.4 我研究了一些关于stackoverflow的答案,不了解我缺少哪些功能。 KB链接不再存在- 我的实现 #include "CrashDumpDef.h" #include "version.h" #ifdef USE_
#include "CrashDumpDef.h"
#include "version.h"
#ifdef USE_MINI_DUMP
#include "CrashDump.h"
#include "FileSystem.h"
LPCWSTR CrashDump::m_szAppName;
LPWSTR CrashDump::m_szAppVersion;
LPWSTR CrashDump::m_szAppBuildNumber;
WCHAR CrashDump::m_szMessageText[MAX_WARNING_MESSAGE_PATH];
LPWSTR CrashDump::m_szDumpFilePath;
#define DEFAULT_MESSAGE_TEXT L"%s Designer has experienced an issue. \nCrash dump has been saved in %s."
#define MAX_DUMP_FILE_NUMBER 9999
CrashDump::CrashDump(LPCWSTR szAppName, LPCWSTR szVersion, LPCWSTR szBuildNumber)
{
// if this assert fires then you have two instances of CrashDump
// which is not allowed
Q_ASSERT(m_szAppName == NULL);
const char* sz = VER_PRODUCTVERSION_STR;
std::vector<wchar_t> vec;
size_t len = strlen(sz);
vec.resize(len + 1);
mbstowcs(&vec[0], sz, len);
const wchar_t* productVersion = &vec[0];
std::string version = VER_PRODUCTVERSION_STR;
char build = version.back();
const char* buildNum = new char(build);
std::vector<wchar_t> vec1;
size_t lenA = strlen(buildNum);
vec1.resize(lenA + 1);
mbstowcs(&vec1[0], buildNum, lenA);
const wchar_t* buildNumber = &vec1[0];
m_szAppName = szAppName ? wcsdup(szAppName) : wcsdup(L"Designer");
m_szAppVersion = productVersion ? wcsdup(productVersion) : wcsdup(productVersion);
m_szAppBuildNumber = buildNumber ? wcsdup(buildNumber) : wcsdup(buildNumber);
wcscpy(m_szMessageText, DEFAULT_MESSAGE_TEXT);
m_szDumpFilePath = NULL;
::SetUnhandledExceptionFilter(TopLevelFilter);
}
CrashDump::~CrashDump()
{
}
void CrashDump::SetVersion(LPCWSTR szVersion)
{
if (szVersion)
{
free(m_szAppVersion);
m_szAppVersion = wcsdup(szVersion);
}
}
void CrashDump::SetBuildNumber(LPCWSTR szBuildNumber)
{
if (szBuildNumber)
{
free(m_szAppBuildNumber);
m_szAppBuildNumber = wcsdup(szBuildNumber);
}
}
void CrashDump::SetDumpFilePath(LPCWSTR szFilePath)
{
free(m_szDumpFilePath);
{
m_szDumpFilePath = wcsdup(szFilePath);
}
}
LONG CrashDump::TopLevelFilter(struct _EXCEPTION_POINTERS *pExceptionInfo)
{
//::MessageBoxW(NULL, L"debugging", m_szAppName, MB_OK);
LONG retval = EXCEPTION_CONTINUE_SEARCH;
HWND hParent = NULL; // find a better value for your app
// firstly see if dbghelp.dll is around and has the function we need
// look next to the EXE first, as the one in System32 might be old
// (e.g. Windows 2000)
HMODULE hDll = NULL;
WCHAR szDbgHelpPath[_MAX_PATH];
if (GetModuleFileName(NULL, szDbgHelpPath, _MAX_PATH))
{
WCHAR *pSlash = wcsrchr(szDbgHelpPath, L'\\');
if (pSlash)
{
wcscpy(pSlash + 1, L"DBGHELP.DLL");
hDll = ::LoadLibrary(szDbgHelpPath);
}
}
if (hDll == NULL)
{
// load any version we can
hDll = ::LoadLibrary(L"DBGHELP.DLL");
}
LPCWSTR szResult = NULL;
if (hDll)
{
MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(hDll, "MiniDumpWriteDump");
if (pDump)
{
WCHAR szDumpPath[_MAX_PATH];
WCHAR szDumpRootPath[_MAX_PATH];
WCHAR szScratch[_MAX_PATH];
// work out a good place for the dump file - add the path here
if (m_szDumpFilePath == NULL)
{
if (GetModuleFileName(NULL, szDbgHelpPath, _MAX_PATH))
{
WCHAR *pSlash = wcsrchr(szDbgHelpPath, L'\\');
if (pSlash)
{
wcscpy(pSlash + 1, L"");
wcscpy(szDumpPath, szDbgHelpPath);
}
}
//else if (!GetTempPath(_MAX_PATH, szDumpPath))
std::string dmpFile = filesystem::buildFilename(QStringList()
<< QDir::toNativeSeparators(QDir::homePath()) + "\\AppData\\Roaming\\ABC\\logs\\"
).toStdString();
std::wstring wideDmpFile;
for (int i = 0; i < dmpFile.length(); ++i)
wideDmpFile += wchar_t(dmpFile[i]);
const wchar_t* szName = wideDmpFile.c_str();
wcscpy(szDumpPath, szName);
}
else
{
wcscpy(szDumpPath, m_szDumpFilePath);
}
wcscpy(szDumpRootPath, szDumpPath);
//PrintDebug(L"[CrashDump] Mini Dump file:[%s]",szDumpPath);
// ask the user if they want to save a dump file
//if (::MessageBox( NULL, _T("Crash, would you like to save a diagnostic file?"), m_szAppName, MB_YESNO )==IDYES)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
int i = 1;
WCHAR szFileNumber[_MAX_PATH];
while (hFile == INVALID_HANDLE_VALUE)
{
swprintf(szFileNumber, sizeof(szFileNumber), L"_%04d", i);
wcscpy(szDumpPath, szDumpRootPath);
wcscat(szDumpPath, m_szAppName);
wcscat(szDumpPath, L"_");
wcscat(szDumpPath, m_szAppVersion);
wcscat(szDumpPath, L"_");
wcscat(szDumpPath, m_szAppBuildNumber);
wcscat(szDumpPath, szFileNumber);
wcscat(szDumpPath, L".dmp");
hFile = ::CreateFile(szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
i++;
if (i > MAX_DUMP_FILE_NUMBER)
{
hFile = ::CreateFile(szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
break;
}
}
// create the file
if (hFile != INVALID_HANDLE_VALUE)
{
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = ::GetCurrentThreadId();
ExInfo.ExceptionPointers = pExceptionInfo;
ExInfo.ClientPointers = NULL;
// write the dump
BOOL bOK = pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);
if (bOK)
{
swprintf(szScratch, sizeof(szScratch), L"Saved dump file to '%s'", szDumpPath);
szResult = szScratch;
retval = EXCEPTION_EXECUTE_HANDLER;
}
else
{
swprintf(szScratch, sizeof(szScratch), L"Failed to save dump file to '%s' (error %d)", szDumpPath, GetLastError());
szResult = szScratch;
}
::CloseHandle(hFile);
WCHAR csOutMessage[MAX_WARNING_MESSAGE_PATH];
swprintf(csOutMessage, sizeof(csOutMessage), m_szMessageText, m_szAppName, szDumpPath);
//PrintError(_T("%s"), csOutMessage);
::MessageBoxW(NULL, csOutMessage, m_szAppName, MB_OK);
}
else
{
swprintf(szScratch, sizeof(szScratch), L"Failed to create dump file '%s' (error %d)", szDumpPath, GetLastError());
szResult = szScratch;
}
}
}
else
{
szResult = L"DBGHELP.DLL too old";
}
}
else
{
szResult = L"DBGHELP.DLL not found";
}
if (szResult)
{
//PrintDebug(_T("[CrashDump] Mini Dump result:[%s]"),szResult);
}
return retval;
}
#endif
#包括“CrashDumpDef.h”
#包括“version.h”
#ifdef使用_MINI_转储
#包括“CrashDump.h”
#包括“FileSystem.h”
LPCWSTR CrashDump::m_szAppName;
LPWSTR CrashDump::m_szAppVersion;
LPWSTR CrashDump::m_szAppBuildNumber;
WCHAR CrashDump::m_szMessageText[MAX_WARNING_MESSAGE_PATH];
LPWSTR CrashDump::m_szDumpFilePath;
#定义默认消息文本“%s”设计器遇到问题。\n刷新转储已保存在%s中
#定义最大转储文件号9999
CrashDump::CrashDump(LPCWSTR szAppName、LPCWSTR szVersion、LPCWSTR szBuildNumber)
{
//如果此断言触发,则有两个CrashDump实例
//这是不允许的
Q_ASSERT(m_szAppName==NULL);
const char*sz=VER\u PRODUCTVERSION\u STR;
std::vec;
尺寸长度=标准长度(sz);
向量调整大小(len+1);
mbstowcs(和vec[0],sz,len);
const wchar_t*productVersion=&vec[0];
std::string version=VER\u PRODUCTVERSION\u STR;
char build=version.back();
const char*buildNum=新字符(构建);
std::vec1;
大小=strlen(buildNum);
vec1.调整大小(lenA+1);
mbstowcs(&vec1[0],buildNum,lenA);
常量wchar_t*buildNumber=&vec1[0];
m_szAppName=szAppName?wcsdup(szAppName):wcsdup(L“设计器”);
m_szAppVersion=productVersion?wcsdup(productVersion):wcsdup(productVersion);
m_szAppBuildNumber=buildNumber?wcsdup(buildNumber):wcsdup(buildNumber);
wcscpy(m_szMessageText,默认_MESSAGE_TEXT);
m_szDumpFilePath=NULL;
::SetUnhandledExceptionFilter(TopLevelFilter);
}
CrashDump::~CrashDump()
{
}
void CrashDump::SetVersion(LPCWSTR szVersion)
{
若有(深圳版)
{
免费(m_szAppVersion);
m_szAppVersion=wcsdup(szAppVersion);
}
}
void CrashDump::SetBuildNumber(LPCWSTR szBuildNumber)
{
if(szBuildNumber)
{
免费(m_szAppBuildNumber);
m_szAppBuildNumber=wcsdup(szBuildNumber);
}
}
void CrashDump::SetDumpFilePath(LPCWSTR szFilePath)
{
自由(m_szDumpFilePath);
{
m_szDumpFilePath=wcsdup(szFilePath);
}
}
LONG CrashDump::TopLevelFilter(结构异常指针*PEExceptionInfo)
{
//::MessageBoxW(NULL,L“调试”,m_szAppName,MB_OK);
LONG retval=异常\继续\搜索;
HWND hParent=NULL;//为应用程序找到更好的值
//首先看看dbghelp.dll是否存在,是否具有我们需要的功能
//首先查看EXE的旁边,因为System32中的那个可能是旧的
//(例如Windows 2000)
HMODULE hDll=NULL;
WCHAR szDbgHelpPath[_MAX_PATH];
if(GetModuleFileName(NULL,szDbgHelpPath,_MAX_PATH))
{
WCHAR*pSlash=wcsrchr(szdbghelpath,L'\\');
if(pSlash)
{
wcscpy(pSlash+1,L“DBGHELP.DLL”);
hDll=::加载库(szDbgHelpPath);
}
}
如果(hDll==NULL)
{
//加载我们可以加载的任何版本
hDll=::LoadLibrary(L“DBGHELP.DLL”);
}
LPCWSTR szResult=NULL;
如果(hDll)
{
MINIDUMPWRITEDUMP pDump=(MINIDUMPWRITEDUMP)::GetProcAddress(hDll,“MINIDUMPWRITEDUMP”);
if(pDump)
{
WCHAR szDumpPath[_MAX_PATH];
WCHAR szDumpRootPath[_MAX_PATH];
WCHAR szScratch[_MAX_PATH];
//为转储文件找到一个好位置-在此处添加路径
if(m_szDumpFilePath==NULL)
{
if(GetModuleFileName(NULL,szDbgHelpPath,_MAX_PATH))
{
WCHAR*pSlash=wcsrchr(szdbghelpath,L'\\');
if(pSlash)
{
wcscpy(pSlash+1,L“);
wcscpy(szDumpPath,szDbgHelpPath);
}
}
//else如果(!GetTempPath(_MAX_PATH,szDumpPath))
std::string dmpFile=filesystem::buildFilename(QStringList())
最大转储(文件号)
{
hFile=::CreateFile(szDumpPath,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,
文件\属性\正常,空);
打破
}
}
//创建文件
if(hFile!=无效的句柄值)
{
_小型转储\异常\信息ExInfo;
ExInfo.ThreadId=::GetCurrentThreadId();
ExInfo.ExceptionPointers=peexceptionfo;
ExInfo.ClientPointers=NULL;
//写入转储文件
BOOL-bOK=pDump(GetCurrentProcess(),GetCurrentProcessId(),hFile,MiniDumpNormal,&ExInfo,NULL,NULL);
如果(bOK)
{
swprintf(szScratch,sizeof(szScratch),L“已将转储文件保存到“%s”,szDumpPath);
szResult=szScratch;
retval=EXCEPTION\u EXECUTE\u处理程序;
}
其他的
{
swprintf(szScratch,sizeof(szScratch),L“未能将转储文件保存到“%s”(错误%d)”,szDumpPath,GetLastError());
szResult=szScratch;