C++ 崩溃转储生成和分析问题

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_

我使用了来自的示例,并在我的应用程序中使用了相同的示例。最近,对于应用程序中的实际崩溃,堆栈跟踪有点无用

另一个问题是生成的dmp文件模块版本不匹配。我已经仔细检查了模块版本,它是相同的,但是转储文件有不同的版本。文件版本为2.8.0.4,dmp文件版本为2.08.0.4

我研究了一些关于stackoverflow的答案,不了解我缺少哪些功能。

KB链接不再存在-

我的实现

#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;