zoukankan      html  css  js  c++  java
  • 让程序在崩溃时输出Dump文件

    #include <Windows.h>  
    #include <tchar.h>   
    #include <DbgHelp.h>  
    #include <iostream>  
    #include <vector>
    
    // 添加对dbghelp.lib的编译依赖  
    //  
    #pragma comment(lib, "dbghelp.lib")  
    
    using namespace std;  
    
    const int MAX_ADDRESS_LENGTH = 32;  
    const int MAX_NAME_LENGTH = 1024;  
    
    // 崩溃信息  
    //   
    struct CrashInfo  
    {  
    	CHAR ErrorCode[MAX_ADDRESS_LENGTH];  
    	CHAR Address[MAX_ADDRESS_LENGTH];  
    	CHAR Flags[MAX_ADDRESS_LENGTH];  
    };  
    
    // CallStack信息  
    //   
    struct CallStackInfo  
    {  
    	CHAR ModuleName[MAX_NAME_LENGTH];  
    	CHAR MethodName[MAX_NAME_LENGTH];  
    	CHAR FileName[MAX_NAME_LENGTH];  
    	CHAR LineNumber[MAX_NAME_LENGTH];  
    };  
    
    // 安全拷贝字符串函数  
    //  
    void SafeStrCpy(char* szDest, size_t nMaxDestSize, const char* szSrc)  
    {  
    	if (nMaxDestSize <= 0) return;  
    	if (strlen(szSrc) < nMaxDestSize)  
    	{  
    		strcpy_s(szDest, nMaxDestSize, szSrc);  
    	}  
    	else  
    	{  
    		strncpy_s(szDest, nMaxDestSize, szSrc, nMaxDestSize);  
    		szDest[nMaxDestSize-1] = '';  
    	}  
    }    
    
    // 得到程序崩溃信息  
    //  
    CrashInfo GetCrashInfo(const EXCEPTION_RECORD *pRecord)  
    {  
    	CrashInfo crashinfo;  
    	SafeStrCpy(crashinfo.Address, MAX_ADDRESS_LENGTH, "N/A");  
    	SafeStrCpy(crashinfo.ErrorCode, MAX_ADDRESS_LENGTH, "N/A");  
    	SafeStrCpy(crashinfo.Flags, MAX_ADDRESS_LENGTH, "N/A");  
    
    	sprintf_s(crashinfo.Address, "%08X", pRecord->ExceptionAddress);  
    	sprintf_s(crashinfo.ErrorCode, "%08X", pRecord->ExceptionCode);  
    	sprintf_s(crashinfo.Flags, "%08X", pRecord->ExceptionFlags);  
    
    	return crashinfo;  
    }  
    
    // 得到CallStack信息  
    //  
    vector<CallStackInfo> GetCallStack(const CONTEXT *pContext)  
    {  
    	HANDLE hProcess = GetCurrentProcess();  
    
    	SymInitialize(hProcess, NULL, TRUE);  
    
    	vector<CallStackInfo> arrCallStackInfo;  
    
    	CONTEXT c = *pContext;  
    
    	STACKFRAME64 sf;  
    	memset(&sf, 0, sizeof(STACKFRAME64));  
    	DWORD dwImageType = IMAGE_FILE_MACHINE_I386;  
    
    	// 不同的CPU类型,具体信息可查询MSDN  
    	//  
    #ifdef _M_IX86  
    	sf.AddrPC.Offset = c.Eip;  
    	sf.AddrPC.Mode = AddrModeFlat;  
    	sf.AddrStack.Offset = c.Esp;  
    	sf.AddrStack.Mode = AddrModeFlat;  
    	sf.AddrFrame.Offset = c.Ebp;  
    	sf.AddrFrame.Mode = AddrModeFlat;  
    #elif _M_X64  
    	dwImageType = IMAGE_FILE_MACHINE_AMD64;  
    	sf.AddrPC.Offset = c.Rip;  
    	sf.AddrPC.Mode = AddrModeFlat;  
    	sf.AddrFrame.Offset = c.Rsp;  
    	sf.AddrFrame.Mode = AddrModeFlat;  
    	sf.AddrStack.Offset = c.Rsp;  
    	sf.AddrStack.Mode = AddrModeFlat;  
    #elif _M_IA64  
    	dwImageType = IMAGE_FILE_MACHINE_IA64;  
    	sf.AddrPC.Offset = c.StIIP;  
    	sf.AddrPC.Mode = AddrModeFlat;  
    	sf.AddrFrame.Offset = c.IntSp;  
    	sf.AddrFrame.Mode = AddrModeFlat;  
    	sf.AddrBStore.Offset = c.RsBSP;  
    	sf.AddrBStore.Mode = AddrModeFlat;  
    	sf.AddrStack.Offset = c.IntSp;  
    	sf.AddrStack.Mode = AddrModeFlat;  
    #else  
    #error "Platform not supported!"  
    #endif  
    
    	HANDLE hThread = GetCurrentThread();  
    
    	while (true)  
    	{  
    		// 该函数是实现这个功能的最重要的一个函数  
    		// 函数的用法以及参数和返回值的具体解释可以查询MSDN  
    		//  
    		if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))  
    		{  
    			break;  
    		}  
    
    		if (sf.AddrFrame.Offset == 0)  
    		{  
    			break;  
    		}  
    
    		CallStackInfo callstackinfo;  
    		SafeStrCpy(callstackinfo.MethodName, MAX_NAME_LENGTH, "N/A");  
    		SafeStrCpy(callstackinfo.FileName, MAX_NAME_LENGTH, "N/A");  
    		SafeStrCpy(callstackinfo.ModuleName, MAX_NAME_LENGTH, "N/A");  
    		SafeStrCpy(callstackinfo.LineNumber, MAX_NAME_LENGTH, "N/A");  
    
    		BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH];  
    		IMAGEHLP_SYMBOL64 *pSymbol = (IMAGEHLP_SYMBOL64*)symbolBuffer;  
    		memset(pSymbol, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH);  
    
    		pSymbol->SizeOfStruct = sizeof(symbolBuffer);  
    		pSymbol->MaxNameLength = MAX_NAME_LENGTH;  
    
    		DWORD symDisplacement = 0;  
    
    		// 得到函数名  
    		//  
    		if (SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, NULL, pSymbol))  
    		{  
    			SafeStrCpy(callstackinfo.MethodName, MAX_NAME_LENGTH, pSymbol->Name);  
    		}  
    
    		IMAGEHLP_LINE64 lineInfo;  
    		memset(&lineInfo, 0, sizeof(IMAGEHLP_LINE64));  
    
    		lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);  
    
    		DWORD dwLineDisplacement;  
    
    		// 得到文件名和所在的代码行  
    		//  
    		if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))  
    		{  
    			SafeStrCpy(callstackinfo.FileName, MAX_NAME_LENGTH, lineInfo.FileName);  
    			sprintf_s(callstackinfo.LineNumber, "%d", lineInfo.LineNumber);  
    		}  
    
    		IMAGEHLP_MODULE64 moduleInfo;  
    		memset(&moduleInfo, 0, sizeof(IMAGEHLP_MODULE64));  
    
    		moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);  
    
    		// 得到模块名  
    		//  
    		if (SymGetModuleInfo64(hProcess, sf.AddrPC.Offset, &moduleInfo))  
    		{  
    			SafeStrCpy(callstackinfo.ModuleName, MAX_NAME_LENGTH, moduleInfo.ModuleName);  
    		}  
    
    		arrCallStackInfo.push_back(callstackinfo);  
    	}  
    
    	SymCleanup(hProcess);  
    
    	return arrCallStackInfo;  
    }  
    
    // 创建Dump文件  
    //   
    void CreateDumpFile(LPCWSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)  
    {  
    	// 创建Dump文件  
    	//  
    	HANDLE hDumpFile = CreateFile(lpstrDumpFilePathName, 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文件内容  
    	//  
    	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);  
    
    	CloseHandle(hDumpFile);  
    } 
    
    // 处理Unhandled Exception的回调函数  
    //  
    LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)  
    {     
    	// 确保有足够的栈空间  
    	//  
    #ifdef _M_IX86  
    	if (pException->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)  
    	{  
    		static char TempStack[1024 * 128];  
    		__asm mov eax,offset TempStack[1024 * 128];  
    		__asm mov esp,eax;  
    	}  
    #endif    
    
    	CrashInfo crashinfo = GetCrashInfo(pException->ExceptionRecord);  
    
    	// 输出Crash信息  
    	//  
    	cout << "ErrorCode: " << crashinfo.ErrorCode << endl;  
    	cout << "Address: " << crashinfo.Address << endl;  
    	cout << "Flags: " << crashinfo.Flags << endl;  
    
    	vector<CallStackInfo> arrCallStackInfo = GetCallStack(pException->ContextRecord);  
    
    	// 输出CallStack  
    	//  
    	cout << "CallStack: " << endl;  
    	for (vector<CallStackInfo>::iterator i = arrCallStackInfo.begin(); i != arrCallStackInfo.end(); ++i)  
    	{  
    		CallStackInfo callstackinfo = (*i);  
    
    		cout << callstackinfo.MethodName << "() : [" << callstackinfo.ModuleName << "] (File: " << callstackinfo.FileName << " @Line " << callstackinfo.LineNumber << ")" << endl;  
    	}  
    
    	CreateDumpFile(_T("C:\Test.dmp"), pException);  
    
    	// 这里弹出一个错误对话框并退出程序  
    	//  
    	FatalAppExit(-1,  _T("Unhandled Exception!"));  
    
    	return EXCEPTION_EXECUTE_HANDLER;  
    }  
    
    int main(int argc, char* argv[])    
    {   
    	// 设置处理Unhandled Exception的回调函数    
    	//     
    	SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);   
    	// 除零,人为的使程序崩溃    
    	//    
    	int i = 13;    
    	int j = 0;    
    	int k = i / j;    
    
    	return 0;    
    }    

    点击打开链接

  • 相关阅读:
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(2)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(10)
    CKEditor在asp.net环境下的使用一例
    《Microsoft Sql server 2008 Internals》读书笔记第五章Table(7)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(11)
    千万数据的连续ID表,快速读取其中指定的某1000条数据?
    javascript中的float运算精度
    .Net与Java的互操作(.NET StockTrader微软官方示例应用程序)
    《Microsoft Sql server 2008 Internals》读书笔记第十一章DBCC Internals(6)
  • 原文地址:https://www.cnblogs.com/byfei/p/6389660.html
Copyright © 2011-2022 走看看