国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump

這篇具有很好參考價(jià)值的文章主要介紹了【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1、簡(jiǎn)介

并不是所有的bug都可以在發(fā)布前找到,也就是說并不是所有的拋出異常的bug都可以在發(fā)布前找到。幸運(yùn)的是,微軟在 Platform SDK 中包含了一個(gè)功能,可以幫助開發(fā)人員收集用戶發(fā)現(xiàn)的異常信息。MiniDumpWriteDump函數(shù)將必要的故障轉(zhuǎn)儲(chǔ)信息寫入文件,而不節(jié)省整個(gè)進(jìn)程空間。此故障轉(zhuǎn)儲(chǔ)信息文件稱為小型轉(zhuǎn)儲(chǔ)。這篇技術(shù)文章提供了有關(guān)如何編寫和使用小型轉(zhuǎn)儲(chǔ)的信息。

1.1 MiniDumpWriteDump函數(shù)

minidump 函數(shù)為應(yīng)用程序提供了一種方法來生成包含整個(gè)進(jìn)程上下文的有用子集的故障轉(zhuǎn)儲(chǔ)文件;這稱為小型轉(zhuǎn)儲(chǔ)文件。以下函數(shù)用于小型轉(zhuǎn)儲(chǔ)文件。將用戶模式小型轉(zhuǎn)儲(chǔ)信息寫入指定文件。

MiniDumpCallback
MiniDumpReadDumpStream
MiniDumpWriteDump
BOOL MiniDumpWriteDump(
  [in] HANDLE                            hProcess,
  [in] DWORD                             ProcessId,
  [in] HANDLE                            hFile,
  [in] MINIDUMP_TYPE                     DumpType,
  [in] PMINIDUMP_EXCEPTION_INFORMATION   ExceptionParam,
  [in] PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  [in] PMINIDUMP_CALLBACK_INFORMATION    CallbackParam
);

如果可能的話,應(yīng)該從一個(gè)單獨(dú)的進(jìn)程調(diào)用MiniDumpWriteDump ,而不是從被轉(zhuǎn)儲(chǔ)的目標(biāo)進(jìn)程中調(diào)用。當(dāng)目標(biāo)進(jìn)程已經(jīng)不穩(wěn)定時(shí)尤其如此。例如,如果它剛剛崩潰。加載程序死鎖是從目標(biāo)進(jìn)程中調(diào)用MiniDumpWriteDump的許多潛在副作用之一 。

MiniDumpWriteDump是 DBGHELP 庫的一部分。這個(gè)庫不是線程安全的,所以任何使用MiniDumpWriteDump的程序都應(yīng)該在嘗試調(diào)用MiniDumpWriteDump之前同步所有線程。請(qǐng)注意,MiniDumpWriteDump當(dāng)前不適用于托管代碼,僅適用于 Windows XP、Windows Vista、Windows 7。

MiniDumpWriteDump可能不會(huì)為調(diào)用線程生成有效的堆棧跟蹤。要解決此問題,您必須在調(diào)用MiniDumpWriteDump之前捕獲調(diào)用線程的狀態(tài)并將其用作 ExceptionParam參數(shù)。一種方法是在 __try / __except塊內(nèi)強(qiáng)制異常,并使用 GetExceptionInformation提供的EXCEPTION_POINTERS信息 ?;蛘撸梢詮男碌墓ぷ骶€程調(diào)用該函數(shù)并從轉(zhuǎn)儲(chǔ)中過濾此工作線程。

1.2 Visual Studio分析小型轉(zhuǎn)儲(chǔ)

  • 打開 Visual Studio。
  • 在文件菜單上,單擊打開項(xiàng)目。
  • 將Files of type設(shè)置為Dump Files,導(dǎo)航到轉(zhuǎn)儲(chǔ)文件,選擇它,然后單擊Open。
  • 運(yùn)行調(diào)試器。
  • 調(diào)試器將創(chuàng)建一個(gè)模擬進(jìn)程。模擬過程將在導(dǎo)致崩潰的指令處停止。

1.3 使用 Microsoft 公共符號(hào)服務(wù)器

要獲取驅(qū)動(dòng)程序級(jí)或系統(tǒng)級(jí)崩潰的堆棧,可能需要將 Visual Studio 配置為指向 Microsoft 公共符號(hào)服務(wù)器。

  • 在“調(diào)試”菜單上,單擊“選項(xiàng)” 。
  • 在選項(xiàng)對(duì)話框中,打開調(diào)試節(jié)點(diǎn),然后單擊符號(hào)。
  • 確保未選擇僅在手動(dòng)加載符號(hào)時(shí)搜索上述位置,除非您想在調(diào)試時(shí)手動(dòng)加載符號(hào)。
  • 如果您在遠(yuǎn)程符號(hào)服務(wù)器上使用符號(hào),則可以通過指定可以將符號(hào)復(fù)制到的本地目錄來提高性能。為此,請(qǐng)輸入從符號(hào)服務(wù)器到此目錄的緩存符號(hào)路徑。要連接到 Microsoft 公共符號(hào)服務(wù)器,您需要啟用此設(shè)置。請(qǐng)注意,如果您在遠(yuǎn)程計(jì)算機(jī)上調(diào)試程序,則緩存目錄是指遠(yuǎn)程計(jì)算機(jī)上的目錄。
  • 單擊確定。
  • 因?yàn)槟褂玫氖?Microsoft 公共符號(hào)服務(wù)器,所以會(huì)出現(xiàn)一個(gè)最終用戶許可協(xié)議對(duì)話框。單擊“是”接受協(xié)議并將符號(hào)下載到本地緩存。

1.4 使用 WinDbg 調(diào)試小型轉(zhuǎn)儲(chǔ)

您還可以使用 WinDbg(作為 Windows 調(diào)試工具的一部分的調(diào)試器)來調(diào)試小型轉(zhuǎn)儲(chǔ)。WinDbg 允許您在不使用 Visual Studio 的情況下進(jìn)行調(diào)試。要下載 Windows 調(diào)試工具,請(qǐng)參閱Windows Hardware Developer Central上的Windows 調(diào)試工具。

  • 安裝 Windows 調(diào)試工具后,必須在 WinDbg 中輸入符號(hào)路徑。
  • 在 WinDbg 中輸入符號(hào)路徑
  • 在文件菜單上,單擊符號(hào)路徑。
  • 在符號(hào)搜索路徑窗口中,輸入以下內(nèi)容:
    “srv*c:\cache*https://msdl.microsoft.com/download/symbols;”

2、代碼實(shí)現(xiàn)

PDB(Program Data Base),意即程序的基本數(shù)據(jù),是VS編譯鏈接時(shí)生成的文件。PDB文件主要存儲(chǔ)了VS調(diào)試程序時(shí)所需要的基本信息,主要包括源文件名、變量名、函數(shù)名、FPO(幀指針)、對(duì)應(yīng)的行號(hào)等等。因?yàn)榇鎯?chǔ)的是調(diào)試信息,所以一般情況下PDB文件是在Debug模式下才會(huì)生成。在VS中可以進(jìn)行設(shè)置,在Release版本中也可以生成PDB文件。
在Release下設(shè)置兩處地方即可生成PDB文件:
【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump
【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump
將如下代碼在程序初始化的時(shí)候執(zhí)行,等待程序運(yùn)行崩潰。
在打開EXE崩潰后,生成.dump文件,將其拷貝至包含exe和pdb文件同一目錄,使用visual studio打開dump文件,即可進(jìn)行調(diào)試。

2.1 例子一

#include <iostream>
#include <Windows.h>
#include <Dbghelp.h>
#include <strsafe.h>
#include <time.h>
#include <shellapi.h>
#include <shlobj.h>

int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
	BOOL bMiniDumpSuccessful;
	WCHAR szPath[MAX_PATH];
	WCHAR szFileName[MAX_PATH];
	const WCHAR* szAppName = L"AppName";
	const WCHAR* szVersion = L"v1.0";
	DWORD dwBufferSize = MAX_PATH;
	HANDLE hDumpFile;
	SYSTEMTIME stLocalTime;
	MINIDUMP_EXCEPTION_INFORMATION ExpParam;

	GetLocalTime(&stLocalTime);
	GetTempPath(dwBufferSize, szPath);

	StringCchPrintf(szFileName, MAX_PATH, L"%s%s", szPath, szAppName);
	CreateDirectory(szFileName, NULL);

	StringCchPrintf(szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
		szPath, szAppName, szVersion,
		stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
		stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
		GetCurrentProcessId(), GetCurrentThreadId());
	hDumpFile = CreateFile(szFileName, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);

	ExpParam.ThreadId = GetCurrentThreadId();
	ExpParam.ExceptionPointers = pExceptionPointers;
	ExpParam.ClientPointers = TRUE;

	bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
		hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);

	return EXCEPTION_EXECUTE_HANDLER;
}

void SomeFunction()
{
	__try
	{
		int *pBadPtr = NULL;
		*pBadPtr = 0;
	}
	__except (GenerateDump(GetExceptionInformation()))
	{
	}
}

2.2 例子二

  • MiniDumper.h:
#ifndef MINIDUMPER_H
#define MINIDUMPER_H
 
#include <windows.h>
 
class CMiniDumper
{
public:
 
    CMiniDumper(bool bPromptUserForMiniDump);
    ~CMiniDumper(void);
 
private:
 
    static LONG WINAPI unhandledExceptionHandler(struct _EXCEPTION_POINTERS *pExceptionInfo);
    void setMiniDumpFileName(void);
    bool getImpersonationToken(HANDLE* phToken);
    BOOL enablePrivilege(LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld);
    BOOL restorePrivilege(HANDLE hToken, TOKEN_PRIVILEGES* ptpOld);
    LONG writeMiniDump(_EXCEPTION_POINTERS *pExceptionInfo );
 
    _EXCEPTION_POINTERS *m_pExceptionInfo;
    TCHAR m_szMiniDumpPath[MAX_PATH];
    TCHAR m_szAppPath[MAX_PATH];
    TCHAR m_szAppBaseName[MAX_PATH];
    bool m_bPromptUserForMiniDump;
 
    static CMiniDumper* s_pMiniDumper;
    static LPCRITICAL_SECTION s_pCriticalSection;
};
 
#endif // MINIDUMPER_H
  • MiniDumper.cpp:
#include <windows.h>
#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <strsafe.h>
//#include <tchar.h>
#include <dbghelp.h>
#include "miniDumper.h"
 
#ifdef UNICODE
    #define _tcssprintf wsprintf
    #define tcsplitpath _wsplitpath
#else
    #define _tcssprintf sprintf
    #define tcsplitpath _splitpath
#endif
 
const int USER_DATA_BUFFER_SIZE = 4096;
 
//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
CMiniDumper* CMiniDumper::s_pMiniDumper = NULL;
LPCRITICAL_SECTION CMiniDumper::s_pCriticalSection = NULL;
 
// Based on dbghelp.h
typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess,
                                         DWORD dwPid,
                                         HANDLE hFile,
                                         MINIDUMP_TYPE DumpType,
                                         CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
                                         CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
                                         CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
 
//-----------------------------------------------------------------------------
// Name: CMiniDumper()
// Desc: Constructor
//-----------------------------------------------------------------------------
CMiniDumper::CMiniDumper( bool bPromptUserForMiniDump )
{
	// Our CMiniDumper should act alone as a singleton.
	assert( !s_pMiniDumper );
 
    s_pMiniDumper = this;
    m_bPromptUserForMiniDump = bPromptUserForMiniDump;
 
    // The SetUnhandledExceptionFilter function enables an application to 
    // supersede the top-level exception handler of each thread and process.
    // After calling this function, if an exception occurs in a process 
    // that is not being debugged, and the exception makes it to the 
    // unhandled exception filter, that filter will call the exception 
    // filter function specified by the lpTopLevelExceptionFilter parameter.
	::SetUnhandledExceptionFilter( unhandledExceptionHandler );
 
    // Since DBGHELP.dll is not inherently thread-safe, making calls into it 
    // from more than one thread simultaneously may yield undefined behavior. 
    // This means that if your application has multiple threads, or is 
    // called by multiple threads in a non-synchronized manner, you need to  
    // make sure that all calls into DBGHELP.dll are isolated via a global
    // critical section.
    s_pCriticalSection = new CRITICAL_SECTION;
 
    if( s_pCriticalSection )
        InitializeCriticalSection( s_pCriticalSection );
}
 
//-----------------------------------------------------------------------------
// Name: ~CMiniDumper()
// Desc: Destructor
//-----------------------------------------------------------------------------
CMiniDumper::~CMiniDumper( void )
{
    if( s_pCriticalSection )
    {
        DeleteCriticalSection( s_pCriticalSection );
        delete s_pCriticalSection;
    }
}
 
//-----------------------------------------------------------------------------
// Name: unhandledExceptionHandler()
// Desc: Call-back filter function for unhandled exceptions
//-----------------------------------------------------------------------------
LONG CMiniDumper::unhandledExceptionHandler( _EXCEPTION_POINTERS *pExceptionInfo )
{
	if( !s_pMiniDumper )
		return EXCEPTION_CONTINUE_SEARCH;
 
	return s_pMiniDumper->writeMiniDump( pExceptionInfo );
}
 
//-----------------------------------------------------------------------------
// Name: setMiniDumpFileName()
// Desc: 
//-----------------------------------------------------------------------------
void CMiniDumper::setMiniDumpFileName( void )
{
    time_t currentTime;
    time( ¤tTime );
 
    wsprintf( m_szMiniDumpPath,
				 L"%s%s.%ld.dmp",
                 m_szAppPath,
                 m_szAppBaseName,
                 currentTime );
}
 
//-----------------------------------------------------------------------------
// Name: getImpersonationToken()
// Desc: The method acts as a potential workaround for the fact that the 
//       current thread may not have a token assigned to it, and if not, the 
//       process token is received.
//-----------------------------------------------------------------------------
bool CMiniDumper::getImpersonationToken( HANDLE* phToken )
{
    *phToken = NULL;
 
    if( !OpenThreadToken( GetCurrentThread(),
                          TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
                          TRUE,
                          phToken) )
    {
        if( GetLastError() == ERROR_NO_TOKEN )
        {
            // No impersonation token for the current thread is available. 
            // Let's go for the process token instead.
            if( !OpenProcessToken( GetCurrentProcess(),
                                   TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
                                   phToken) )
                return false;
        }
        else
            return false;
    }
 
    return true;
}
 
//-----------------------------------------------------------------------------
// Name: enablePrivilege()
// Desc: Since a MiniDump contains a lot of meta-data about the OS and 
//       application state at the time of the dump, it is a rather privileged 
//       operation. This means we need to set the SeDebugPrivilege to be able 
//       to call MiniDumpWriteDump.
//-----------------------------------------------------------------------------
BOOL CMiniDumper::enablePrivilege( LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
{
    BOOL bOk = FALSE;
 
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    bOk = LookupPrivilegeValue( 0, pszPriv, &tp.Privileges[0].Luid );
 
    if( bOk )
    {
        DWORD cbOld = sizeof(*ptpOld);
        bOk = AdjustTokenPrivileges( hToken, FALSE, &tp, cbOld, ptpOld, &cbOld );
    }
 
    return (bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()));
}
 
//-----------------------------------------------------------------------------
// Name: restorePrivilege()
// Desc: 
//-----------------------------------------------------------------------------
BOOL CMiniDumper::restorePrivilege( HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
{
    BOOL bOk = AdjustTokenPrivileges(hToken, FALSE, ptpOld, 0, NULL, NULL);
    return ( bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()) );
}
 
//-----------------------------------------------------------------------------
// Name: writeMiniDump()
// Desc: 
//-----------------------------------------------------------------------------
LONG CMiniDumper::writeMiniDump( _EXCEPTION_POINTERS *pExceptionInfo )
{
	LONG retval = EXCEPTION_CONTINUE_SEARCH;
	m_pExceptionInfo = pExceptionInfo;
 
    HANDLE hImpersonationToken = NULL;
    if( !getImpersonationToken( &hImpersonationToken ) )
        return FALSE;
 
	// You have to find the right dbghelp.dll. 
	// Look next to the EXE first since the one in System32 might be old (Win2k)
	
	HMODULE hDll = NULL;
	TCHAR szDbgHelpPath[MAX_PATH];
 
	if( GetModuleFileName( NULL, m_szAppPath, _MAX_PATH ) )
	{
		TCHAR *pSlash = wcsrchr( m_szAppPath, '\\' );
 
		if( pSlash )
		{
			_tcscpy( m_szAppBaseName, pSlash + 1);
			*(pSlash+1) = 0;
		}
 
		wcscpy( szDbgHelpPath, m_szAppPath );
        wcscat( szDbgHelpPath, L"DBGHELP.DLL");
		hDll = ::LoadLibrary( szDbgHelpPath );
	}
 
	if( hDll == NULL )
	{
		// If we haven't found it yet - try one more time.
		hDll = ::LoadLibrary( L"DBGHELP.DLL");
	}
 
	LPCTSTR szResult = NULL;
 
	if( hDll )
	{
        // Get the address of the MiniDumpWriteDump function, which writes 
        // user-mode mini-dump information to a specified file.
		MINIDUMPWRITEDUMP MiniDumpWriteDump = 
            (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
 
		if( MiniDumpWriteDump != NULL )
        {
			TCHAR szScratch[USER_DATA_BUFFER_SIZE];
 
			setMiniDumpFileName();
 
			// Ask the user if he or she wants to save a mini-dump file...
			wsprintf( szScratch,
                         L"There was an unexpected error:\n\nWould you "
                         L"like to create a mini-dump file?\n\n%s ",
                         m_szMiniDumpPath);
 
			// Create the mini-dump file...
			HANDLE hFile = ::CreateFile( m_szMiniDumpPath, 
                                            GENERIC_WRITE, 
                                            FILE_SHARE_WRITE, 
                                            NULL, 
                                            CREATE_ALWAYS, 
                                            FILE_ATTRIBUTE_NORMAL, 
                                            NULL );
 
			if( hFile != INVALID_HANDLE_VALUE )
			{
				_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
				ExInfo.ThreadId          = ::GetCurrentThreadId();
				ExInfo.ExceptionPointers = pExceptionInfo;
				ExInfo.ClientPointers    = NULL;
 
                // We need the SeDebugPrivilege to be able to run MiniDumpWriteDump
                TOKEN_PRIVILEGES tp;
                BOOL bPrivilegeEnabled = enablePrivilege( SE_DEBUG_NAME, hImpersonationToken, &tp );
 
                BOOL bOk;
 
                // DBGHELP.dll is not thread-safe, so we need to restrict access...
                EnterCriticalSection( s_pCriticalSection );
                {
					// Write out the mini-dump data to the file...
                    bOk = MiniDumpWriteDump( GetCurrentProcess(),
                                                GetCurrentProcessId(),
                                                hFile,
                                                MiniDumpNormal,
                                                &ExInfo,
                                                NULL,
                                                NULL );
                }
                LeaveCriticalSection( s_pCriticalSection );
 
                // Restore the privileges when done
                if( bPrivilegeEnabled )
	                restorePrivilege( hImpersonationToken, &tp );
 
                if( bOk )
				{
					szResult = NULL;
					retval = EXCEPTION_EXECUTE_HANDLER;
				}
				else
				{
					wsprintf( szScratch,
                                    L"Failed to save the mini-dump file to '%s' (error %d)",
                                    m_szMiniDumpPath,
                                    GetLastError() );
 
					szResult = szScratch;
				}
 
				::CloseHandle( hFile );
			}
			else
			{
				wsprintf( szScratch,
                                L"Failed to create the mini-dump file '%s' (error %d)",
                                m_szMiniDumpPath,
                                GetLastError() );
 
				szResult = szScratch;
			}
		}
		else
		{
			szResult = L"Call to GetProcAddress failed to find MiniDumpWriteDump. "
                       L"The DBGHELP.DLL is possibly outdated." ;
		}
	}
	else
	{
		szResult = L"Call to LoadLibrary failed to find DBGHELP.DLL.";
	}
 
	if( szResult && m_bPromptUserForMiniDump )
		::MessageBox( NULL, szResult, NULL, MB_OK );
 
	TerminateProcess( GetCurrentProcess(), 0 );
 
	return retval;
}
 
  • test.cpp:
#include "MiniDumper.h"
CMiniDumper g_miniDumper( true );

2.3 例子三

  • MiniDump.h
#pragma once
#include <Windows.h>
#include <tchar.h>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")

#ifdef UNICODE
#define TSprintf	wsprintf
#else
#define TSprintf	sprintf
#endif

class MiniDump
{
private:
	MiniDump();
	~MiniDump();

public:
	// 程序崩潰時(shí)是否啟動(dòng)自動(dòng)生成dump文件;
	// 只需要在main函數(shù)開始處調(diào)用該函數(shù)即可;
	static void EnableAutoDump(bool bEnable = true);

private:

	static LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException);
	static void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException);
};
  • MiniDump.cpp
#include "MiniDump.h"

MiniDump::MiniDump()
{
}

MiniDump::~MiniDump()
{
}

void MiniDump::EnableAutoDump(bool bEnable)
{
	if (bEnable)
	{
		SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) ApplicationCrashHandler);
	}
}

LONG MiniDump::ApplicationCrashHandler(EXCEPTION_POINTERS *pException)
{
	/*if (IsDebuggerPresent())
	{
		return EXCEPTION_CONTINUE_SEARCH;
	}*/

	TCHAR szDumpDir[MAX_PATH] = { 0 };
	TCHAR szDumpFile[MAX_PATH] = { 0 };
	TCHAR szMsg[MAX_PATH] = { 0 };
	SYSTEMTIME	stTime = { 0 };
	// 構(gòu)建dump文件路徑;
	GetLocalTime(&stTime);
	::GetCurrentDirectory(MAX_PATH, szDumpDir);
	TSprintf(szDumpFile, _T("%s\\%04d%02d%02d_%02d%02d%02d.dmp"), szDumpDir,
		stTime.wYear, stTime.wMonth, stTime.wDay,
		stTime.wHour, stTime.wMinute, stTime.wSecond);
	// 創(chuàng)建dump文件;
	CreateDumpFile(szDumpFile, pException);

	// 彈出一個(gè)錯(cuò)誤對(duì)話框或者提示上傳, 并退出程序;
	TSprintf(szMsg, _T("I'm so sorry, but the program crashed.\r\ndump file : %s"), szDumpFile);
	FatalAppExit(-1, szMsg);

	return EXCEPTION_EXECUTE_HANDLER;
}

void MiniDump::CreateDumpFile(LPCWSTR strPath, EXCEPTION_POINTERS *pException)
{
	// 創(chuàng)建Dump文件;
	HANDLE hDumpFile = CreateFile(strPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	// Dump信息;
	MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
	dumpInfo.ExceptionPointers = pException;
	dumpInfo.ThreadId = GetCurrentThreadId();
	dumpInfo.ClientPointers = TRUE;

	// 寫入Dump文件內(nèi)容;
	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);
	CloseHandle(hDumpFile);
}

2.4 例子四

CrashRpt是一個(gè)免費(fèi)的開源庫,旨在攔截 C++ 程序中的異常、收集有關(guān)崩潰的技術(shù)信息并通過 Internet 向軟件供應(yīng)商發(fā)送錯(cuò)誤報(bào)告。

http://crashrpt.sourceforge.net/docs/html/getting_started.html
【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
// Include CrashRpt Header 
#include "CrashRpt.h"

FILE* g_hLog = NULL; // Global handle to the application log file

// Define the callback function that will be called on crash
int CALLBACK CrashCallback(CR_CRASH_CALLBACK_INFO* pInfo)
{  
  // The application has crashed!

  // Close the log file here
  // to ensure CrashRpt is able to include it into error report
  if(g_hLog!=NULL)
  {
    fclose(g_hLog);
    g_hLog = NULL;// Clean up handle
  }

  // Return CR_CB_DODEFAULT to generate error report
  return CR_CB_DODEFAULT;
}

// The following function writes an entry to the log file
void log_write(LPCTSTR szFormat, ...)
{
  if (g_hLog == NULL) 
    return; // Log file seems to be closed

  va_list args; 
  va_start(args); 
  _vftprintf_s(g_hLog, szFormat, args);
  fflush(g_hLog);
}

// Thread procedure
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
  // Install exception handlers for this thread
  crInstallToCurrentThread2(0);

  log_write(_T("Entering the thread proc\n"));

  // Define the infinite loop where some processing will be done 
  for(;;)
  {
    // There is a hidden error somewhere inside of the loop...
    int* p = NULL;
    *p = 13; // This results in Access Violation
  }    
   
  log_write(_T("Leaving the thread proc\n"));

  // Unset exception handlers before exiting the thread
  crUninstallFromCurrentThread();    

  return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{  
  // Define CrashRpt configuration parameters
  CR_INSTALL_INFO info;  
  memset(&info, 0, sizeof(CR_INSTALL_INFO));  
  info.cb = sizeof(CR_INSTALL_INFO);    
  info.pszAppName = _T("MyApp");  
  info.pszAppVersion = _T("1.0.0");  
  info.pszEmailSubject = _T("MyApp 1.0.0 Error Report");  
  info.pszEmailTo = _T("myapp_support@hotmail.com");    
  info.pszUrl = _T("http://myapp.com/tools/crashrpt.php");  
  info.uPriorities[CR_HTTP] = 3;  // First try send report over HTTP 
  info.uPriorities[CR_SMTP] = 2;  // Second try send report over SMTP  
  info.uPriorities[CR_SMAPI] = 1; // Third try send report over Simple MAPI    
  // Install all available exception handlers
  info.dwFlags |= CR_INST_ALL_POSSIBLE_HANDLERS;
  // Restart the app on crash 
  info.dwFlags |= CR_INST_APP_RESTART; 
  info.dwFlags |= CR_INST_SEND_QUEUED_REPORTS; 
  info.pszRestartCmdLine = _T("/restart");
  // Define the Privacy Policy URL 
  info.pszPrivacyPolicyURL = _T("http://myapp.com/privacypolicy.html"); 
  
  // Install crash reporting
  int nResult = crInstall(&info);    
  if(nResult!=0)  
  {    
    // Something goes wrong. Get error message.
    TCHAR szErrorMsg[512] = _T("");        
    crGetLastErrorMsg(szErrorMsg, 512);    
    _tprintf_s(_T("%s\n"), szErrorMsg);    
    return 1;
  } 

  // Set crash callback function
  crSetCrashCallback(CrashCallback, NULL);

  // Add our log file to the error report
  crAddFile2(_T("log.txt"), NULL, _T("Log File"), CR_AF_MAKE_FILE_COPY);    

  // We want the screenshot of the entire desktop is to be added on crash
  crAddScreenshot2(CR_AS_VIRTUAL_SCREEN, 0);   

  // Add a named property that means what graphics adapter is
  // installed on user's machine
  crAddProperty(_T("VideoCard"), _T("nVidia GeForce 8600 GTS"));

  // The main code follows...

  // Open log file
  errno_t err = _tfopen_s(&g_hLog, _T("log.txt"), _T("wt"));
  if(err!=0 || g_hLog==NULL)
  {
    _tprintf_s(_T("Error opening log.txt\n"));
    return 1; // Couldn't open log file
  }

  log_write(_T("Started successfully\n"));

  // Create the worker thread
  HANDLE hWorkingThread = CreateThread(NULL, 0, 
           ThreadProc, (LPVOID)NULL, 0, NULL);

  log_write(_T("Created working thread\n"));

  // There is a hidden error in the main() function
  // Call of _tprintf_s with NULL parameter
  TCHAR* szFormatString = NULL;
  _tprintf_s(szFormatString);

  // Wait until the worker thread is exited
  WaitForSingleObject(hWorkingThread, INFINITE);

  log_write(_T("Working thread has exited\n"));

  // Close the log file
  if(g_hLog!=NULL)
  {
    fclose(g_hLog);
    g_hLog = NULL;// Clean up handle
  }

  // Uninitialize CrashRpt before exiting the main function
  crUninstall();

  // Exit
  return 0;
}

2.5 其他例子

(1)除了 CrashRpt,chromium 里使用的 crashpad 也是一個(gè)非常好的選擇。google 出品,質(zhì)量有保障。
crashpad 的前身是 breakpad。
https://github.com/chromium/crashpad

(2)適用于.NET程序的 CrashReporter。
https://github.com/ravibpatel/CrashReporter.NET

(3)其它平臺(tái)(Android,iOS等)也有類似的開源庫??梢栽?github 上搜索 crash report。

3、調(diào)試工具

3.1 windbg

Windows 調(diào)試程序 (WinDbg) 可用于調(diào)試內(nèi)核模式和用戶模式代碼、分析故障轉(zhuǎn)儲(chǔ)以及在代碼執(zhí)行時(shí)檢查 CPU 寄存器。

https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/debugger-download-tools

從 SDK 獲取用于 Windows (WinDbg) 的調(diào)試工具:Windows SDK。 使用Windows SDK 頁上的下載鏈接,因?yàn)?Windows 調(diào)試工具在Visual Studio中不可用。

如果你只需要用于Windows的調(diào)試工具,而不是用于Windows的 (WDK) Windows 驅(qū)動(dòng)程序工具包,則可以將調(diào)試工具安裝為Windows軟件開發(fā)工具包 (SDK) 的獨(dú)立組件。

在 SDK 安裝向?qū)е羞x擇“Windows 調(diào)試工具” ,并取消選擇所有其他組件。

3.2 debugdiag

Debug Diagnostic Tool (DebugDiag)是微軟提供的工具,可以用來追蹤windows平臺(tái)下的程序崩潰,卡死,內(nèi)存泄漏等一些疑難問題的原因,按照問題類別配置收集后,反饋給公司技術(shù)人員。

下載后按缺省提示安裝即可:
https://www.microsoft.com/en-US/download/details.aspx?id=58210
https://www.microsoft.com/en-us/download/details.aspx?id=49924
【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump

3.3 Visual Studio

轉(zhuǎn)儲(chǔ)文件是一個(gè)快照,其顯示某個(gè)時(shí)間點(diǎn)正在為應(yīng)用執(zhí)行的進(jìn)程和已為應(yīng)用加載的模塊。 帶堆信息的轉(zhuǎn)儲(chǔ)還包括該時(shí)間點(diǎn)的應(yīng)用內(nèi)存的快照。

在 Visual Studio 中打開帶堆的轉(zhuǎn)儲(chǔ)文件類似于在調(diào)試會(huì)話中在斷點(diǎn)處停止。 盡管你無法繼續(xù)執(zhí)行,但在轉(zhuǎn)儲(chǔ)時(shí)可以檢查應(yīng)用的堆棧、線程和變量值。

轉(zhuǎn)儲(chǔ)最常用于調(diào)試開發(fā)人員無權(quán)訪問的計(jì)算機(jī)中的問題。 當(dāng)你無法在自己的計(jì)算機(jī)上重現(xiàn)崩潰或無響應(yīng)的程序時(shí),可以使用來自客戶計(jì)算機(jī)的轉(zhuǎn)儲(chǔ)文件。 測(cè)試人員還會(huì)創(chuàng)建轉(zhuǎn)儲(chǔ)以保存崩潰或無響應(yīng)程序數(shù)據(jù),從而用于更多測(cè)試。

Visual Studio 調(diào)試器可為托管或本機(jī)代碼保存轉(zhuǎn)儲(chǔ)文件。 它可以調(diào)試由 Visual Studio 或其他以小型轉(zhuǎn)儲(chǔ)格式保存文件的應(yīng)用創(chuàng)建的轉(zhuǎn)儲(chǔ)文件。

【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump
利用VS可以很方便的分析dump文件,如果有生成dump文件時(shí)對(duì)應(yīng)的.pdb文件,就可以直接定位到出錯(cuò)的代碼行。
【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump

PDB (Program Data Base) 即程序的基本數(shù)據(jù),是 VS 編譯鏈接時(shí)生成的文件,每個(gè)程序集(EXE 或 DLL)都有一個(gè)與之對(duì)應(yīng)的 PDB 文件。DPB 文件主要存儲(chǔ)了 VS 調(diào)試程序時(shí)所需要的基本信息,主要包括源文件名、變量名、函數(shù)名、對(duì)應(yīng)的行號(hào)等等。因?yàn)榇鎯?chǔ)的是調(diào)試信息,所以一般情況下 PDB 文件是在 Debug 模式下才會(huì)生成。有了這個(gè)文件,我們才能對(duì)程序進(jìn)行 斷點(diǎn)調(diào)試 ,才能一步步執(zhí)行程序。
【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump

結(jié)語

如果您覺得該方法或代碼有一點(diǎn)點(diǎn)用處,可以給作者點(diǎn)個(gè)贊,或打賞杯咖啡;╮( ̄▽ ̄)╭
如果您感覺方法或代碼不咋地//(ㄒoㄒ)//,就在評(píng)論處留言,作者繼續(xù)改進(jìn);o_O???
如果您需要相關(guān)功能的代碼定制化開發(fā),可以留言私信作者;(????)
感謝各位大佬童鞋們的支持!( ′ ▽′ )? ( ′ ▽′)っ?。。?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-456817.html

到了這里,關(guān)于【小沐學(xué)C++】C++ 捕獲程序異常奔潰minidump的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【小沐學(xué)Web】程序員必備的畫圖工具匯總

    【小沐學(xué)Web】程序員必備的畫圖工具匯總

    《夏》 烈日灼灼, 水波清清, 熱浪濤濤, 爽爽其心。 楊柳依依, 荷葉搖搖, 蜻蜓點(diǎn)點(diǎn), 涼涼其身。 優(yōu)秀的作圖工具有許多,例如文本繪圖工具 PlantUML,流程圖設(shè)計(jì)工具 Draw.io,還有專業(yè)繪圖工具 Sketch 和 Figma 等。 官網(wǎng)地址: https://www.draw.io/index.html https://www.diagrams.net/

    2024年02月07日
    瀏覽(32)
  • 【小沐學(xué)C++】C++ MFC中嵌入web網(wǎng)頁控件(WebBrowser、WebView2、CEF3)

    【小沐學(xué)C++】C++ MFC中嵌入web網(wǎng)頁控件(WebBrowser、WebView2、CEF3)

    WebBrowser控件最常見的用途之一是向應(yīng)用程序添加 Internet 瀏覽功能。使用 IWebBrowser2 接口,可以瀏覽到本地文件系統(tǒng)、網(wǎng)絡(luò)或萬維網(wǎng)上的任何位置??梢允褂肐WebBrowser2::Navigate 方法告知控件要瀏覽到哪個(gè)位置。第一個(gè)參數(shù)是包含位置名稱的字符串。要瀏覽到本地文件系統(tǒng)或網(wǎng)絡(luò)

    2024年02月05日
    瀏覽(93)
  • 【小沐學(xué)Python】Python實(shí)現(xiàn)語音識(shí)別(Whisper)

    【小沐學(xué)Python】Python實(shí)現(xiàn)語音識(shí)別(Whisper)

    https://github.com/openai/whisper Whisper 是一種通用的語音識(shí)別模型。它是在包含各種音頻的大型數(shù)據(jù)集上訓(xùn)練的,也是一個(gè)多任務(wù)模型,可以執(zhí)行多語言語音識(shí)別、語音翻譯和語言識(shí)別。 Open AI在2022年9月21日開源了號(hào)稱其英文語音辨識(shí)能力已達(dá)到人類水準(zhǔn)的Whisper神經(jīng)網(wǎng)絡(luò),且它亦支

    2024年02月04日
    瀏覽(1050)
  • 【小沐學(xué)Python】Python實(shí)現(xiàn)語音識(shí)別(SpeechRecognition)

    【小沐學(xué)Python】Python實(shí)現(xiàn)語音識(shí)別(SpeechRecognition)

    https://pypi.org/project/SpeechRecognition/ https://github.com/Uberi/speech_recognition SpeechRecognition用于執(zhí)行語音識(shí)別的庫,支持多個(gè)引擎和 API,在線和離線。 Speech recognition engine/API 支持如下接口: 以上幾個(gè)中只有 recognition_sphinx()可與CMU Sphinx 引擎脫機(jī)工作, 其他六個(gè)都需要連接互聯(lián)網(wǎng)。另

    2024年02月04日
    瀏覽(96)
  • 【小沐學(xué)寫作】免費(fèi)在線AI輔助寫作匯總

    【小沐學(xué)寫作】免費(fèi)在線AI輔助寫作匯總

    自從chatgpt火了以后,AI工具爆發(fā)式增長(zhǎng),各種各樣的AI工具層出不窮。有Ai寫作、AI繪畫、AI編程、AI視頻、AI音頻等等,今天為大家推薦的這幾款A(yù)I輔助寫作工具。 https://effidit.qq.com/demo 智能創(chuàng)作助手 Effidit(Efficient and Intelligent Editing) 是由騰訊 AI Lab 開發(fā)的一個(gè)研究性原型系統(tǒng)

    2024年02月04日
    瀏覽(46)
  • 【小沐學(xué)NLP】在線AI繪畫網(wǎng)站(百度:文心一格)

    【小沐學(xué)NLP】在線AI繪畫網(wǎng)站(百度:文心一格)

    當(dāng)下,越來越多AI領(lǐng)域前沿技術(shù)爭(zhēng)相落地,逐步釋放出極大的產(chǎn)業(yè)價(jià)值,其中最受關(guān)注的方向之一便是 大規(guī)模預(yù)訓(xùn)練模型(簡(jiǎn)稱“大模型”),大模型不僅效果好、泛化能力強(qiáng)、通用性強(qiáng),而且具有強(qiáng)大的生成能力。在此基礎(chǔ)上,AIGC(Artificial Intelligence Generated Content,人工智

    2024年02月14日
    瀏覽(22)
  • 【小沐學(xué)Web】Rust實(shí)現(xiàn)Web服務(wù)器

    【小沐學(xué)Web】Rust實(shí)現(xiàn)Web服務(wù)器

    https://www.rust-lang.org/ Rust: 一種使每個(gè)人都能夠構(gòu)建可靠且高效的軟件的語言。 如今,全球有數(shù)百家公司在生產(chǎn)環(huán)境中使用 Rust,以提供快速、資源少、跨平臺(tái)的解決方案。您熟悉和喜愛的軟件,例如Firefox、 Dropbox和Cloudflare,都使用 Rust。從初創(chuàng)公司到大公司,從嵌入式設(shè)備到

    2024年02月07日
    瀏覽(28)
  • 【小沐學(xué)Python】Python實(shí)現(xiàn)Web圖表功能(Dash)

    【小沐學(xué)Python】Python實(shí)現(xiàn)Web圖表功能(Dash)

    https://dash.plotly.com/ https://dash.gallery/Portal/ Dash 是一個(gè)用于構(gòu)建Web應(yīng)用程序的 Python 庫,無需 JavaScript 。 Dash是下載量最大,最值得信賴的Python框架,用于構(gòu)建ML和數(shù)據(jù)科學(xué)Web應(yīng)用程序。 Dash是一個(gè)用來創(chuàng)建 web 應(yīng)用的 python 庫,它建立在 Plotly.js(同一個(gè)團(tuán)隊(duì)開發(fā))、React 和 Flask 之上

    2024年02月04日
    瀏覽(96)
  • 【C++】異常處理 ① ( 異常概念引入 | 拋出異常語法 | 捕獲異常語法 | 異常捕獲流程 | 異常處理代碼示例 )

    【C++】異常處理 ① ( 異常概念引入 | 拋出異常語法 | 捕獲異常語法 | 異常捕獲流程 | 異常處理代碼示例 )

    異常是一種 特殊的程序流控制機(jī)制 , 用于處理程序中可能出現(xiàn)的錯(cuò)誤或異常情況 ; 當(dāng)程序執(zhí)行錯(cuò)誤時(shí) , 由 throw 拋出異常 , 并即跳轉(zhuǎn)到相應(yīng)的異常處理程序中 ; 如果沒有適當(dāng)?shù)漠惓L幚沓绦蛱幚碓摦惓?, 程序會(huì)崩潰終止 ; 異常與函數(shù)對(duì)比 : 函數(shù) 是一種 以 棧結(jié)構(gòu) 展開的

    2024年02月04日
    瀏覽(18)
  • 【小沐學(xué)NLP】Python實(shí)現(xiàn)聊天機(jī)器人(微軟小冰)

    【小沐學(xué)NLP】Python實(shí)現(xiàn)聊天機(jī)器人(微軟小冰)

    ??NLP開發(fā)系列相關(guān)文章編寫如下??: 1 ??【小沐學(xué)NLP】Python實(shí)現(xiàn)詞云圖?? 2 ??【小沐學(xué)NLP】Python實(shí)現(xiàn)圖片文字識(shí)別?? 3 ??【小沐學(xué)NLP】Python實(shí)現(xiàn)中文、英文分詞?? 4 ??【小沐學(xué)NLP】Python實(shí)現(xiàn)聊天機(jī)器人(ELIZA))?? 5 ??【小沐學(xué)NLP】Python實(shí)現(xiàn)聊天機(jī)器人(ALICE)?? 6

    2024年02月05日
    瀏覽(95)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包