http://blog.csdn.net/wangningyu/article/details/6748138
?
之前碰到論壇里有幾個(gè)好友,說程序不時(shí)的崩潰,什么xxoo不能read的! 如果光要是這個(gè)內(nèi)存地址,估計(jì)你會(huì)瘋掉~~
所以分享一下基本的調(diào)試技巧,需要準(zhǔn)備的工具有WinDbg + VC6.0,
下面是自己整理的一份自動(dòng)生成DUMP文件的源代碼,只需要添加到工程即可,源代碼如下:
MiniDump.h
?
[cpp] view plaincopyprint? #include?<windows.h> ??#include?<tlhelp32.h> ????????????#pragma?optimize("y",?off)??????//generate?stack?frame?pointers?for?all?functions?-?same?as?/Oy-?in?the?project ??#pragma?warning(disable:?4200)??//nonstandard?extension?used?:?zero-sized?array?in?struct/union ??#pragma?warning(disable:?4100)??//unreferenced?formal?parameter ??????????????#ifndef?_DBGHELP_ ????typedef?struct?_MINIDUMP_EXCEPTION_INFORMATION?{??????DWORD???ThreadId;??????PEXCEPTION_POINTERS?ExceptionPointers;??????BOOL????ClientPointers;??}?MINIDUMP_EXCEPTION_INFORMATION,?*PMINIDUMP_EXCEPTION_INFORMATION;????typedef?enum?_MINIDUMP_TYPE?{??????MiniDumpNormal?=????????????0x00000000,??????????MiniDumpWithDataSegs?=??????0x00000001,??}?MINIDUMP_TYPE;????typedef?BOOL?(WINAPI?*?MINIDUMP_WRITE_DUMP)(??????????????????????????????????????????????IN?HANDLE???????????hProcess,??????????????????????????????????????????????IN?DWORD????????????ProcessId,??????????????????????????????????????????????IN?HANDLE???????????hFile,??????????????????????????????????????????????IN?MINIDUMP_TYPE????DumpType,??????????????????????????????????????????????IN?CONST?PMINIDUMP_EXCEPTION_INFORMATION????ExceptionParam,?OPTIONAL??????????????????????????????????????????????IN?PVOID????????????????????????????????????UserStreamParam,?OPTIONAL??????????????????????????????????????????????IN?PVOID????????????????????????????????????CallbackParam?OPTIONAL??????????????????????????????????????????????);????#else ????typedef?BOOL?(WINAPI?*?MINIDUMP_WRITE_DUMP)(??????????????????????????????????????????????IN?HANDLE???????????hProcess,??????????????????????????????????????????????IN?DWORD????????????ProcessId,??????????????????????????????????????????????IN?HANDLE???????????hFile,??????????????????????????????????????????????IN?MINIDUMP_TYPE????DumpType,??????????????????????????????????????????????IN?CONST?PMINIDUMP_EXCEPTION_INFORMATION????ExceptionParam,?OPTIONAL??????????????????????????????????????????????IN?PMINIDUMP_USER_STREAM_INFORMATION????????UserStreamParam,?OPTIONAL??????????????????????????????????????????????IN?PMINIDUMP_CALLBACK_INFORMATION???????????CallbackParam?OPTIONAL??????????????????????????????????????????????);??#endif?//#ifndef?_DBGHELP_ ??????typedef?HANDLE?(WINAPI?*?CREATE_TOOL_HELP32_SNAPSHOT)(DWORD?dwFlags,?DWORD?th32ProcessID);??typedef?BOOL?(WINAPI?*?MODULE32_FIRST)(HANDLE?hSnapshot,?LPMODULEENTRY32?lpme);??typedef?BOOL?(WINAPI?*?MODULE32_NEST)(HANDLE?hSnapshot,?LPMODULEENTRY32?lpme);??????extern?void?WINAPI?Create_Dump(PEXCEPTION_POINTERS?pException,?BOOL?File_Flag,?BOOL?Show_Flag);????extern?HMODULE??hDbgHelp;??extern?MINIDUMP_WRITE_DUMP??MiniDumpWriteDump_;????extern?CREATE_TOOL_HELP32_SNAPSHOT??CreateToolhelp32Snapshot_;??extern?MODULE32_FIRST???Module32First_;??extern?MODULE32_NEST????Module32Next_;??#include <windows.h> #include <tlhelp32.h> //#include "dbghelp.h" //#define DEBUG_DPRINTF 1 //allow d() //#include "wfun.h" #pragma optimize("y", off) //generate stack frame pointers for all functions - same as /Oy- in the project #pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union #pragma warning(disable: 4100) //unreferenced formal parameter /*BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, PCHAR Module_Name, PBYTE & Module_Addr); int WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, PCHAR Str); int WINAPI Get_Version_Str(PCHAR Str); PCHAR WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException); void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag);*/ // In case you don't have dbghelp.h. #ifndef _DBGHELP_ typedef struct _MINIDUMP_EXCEPTION_INFORMATION { DWORD ThreadId; PEXCEPTION_POINTERS ExceptionPointers; BOOL ClientPointers; } MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; typedef enum _MINIDUMP_TYPE { MiniDumpNormal = 0x00000000, MiniDumpWithDataSegs = 0x00000001, } MINIDUMP_TYPE; typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile, IN MINIDUMP_TYPE DumpType, IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL IN PVOID UserStreamParam, OPTIONAL IN PVOID CallbackParam OPTIONAL ); #else typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( IN HANDLE hProcess, IN DWORD ProcessId, IN HANDLE hFile, IN MINIDUMP_TYPE DumpType, IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL IN PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL IN PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL ); #endif //#ifndef _DBGHELP_ // Tool Help functions. typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); typedef BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); typedef BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); extern void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag); extern HMODULE hDbgHelp; extern MINIDUMP_WRITE_DUMP MiniDumpWriteDump_; extern CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_; extern MODULE32_FIRST Module32First_; extern MODULE32_NEST Module32Next_;
MiniDump.cpp
?
[cpp] view plaincopyprint? ?????????#include?"StdAfx.h" ??#include?"MiniDump.h" ??#include?<Shlwapi.h> ????#pragma?comment(lib,"shlwapi.lib") ????HMODULE?hDbgHelp;??MINIDUMP_WRITE_DUMP?MiniDumpWriteDump_;????CREATE_TOOL_HELP32_SNAPSHOT?CreateToolhelp32Snapshot_;??MODULE32_FIRST??Module32First_;??MODULE32_NEST???Module32Next_;????#define?DUMP_SIZE_MAX???8000????//max?size?of?our?dump ??#define?CALL_TRACE_MAX??((DUMP_SIZE_MAX?-?2000)?/?(MAX_PATH?+?40))??//max?number?of?traced?calls ??#define?NL??????????????"\r\n"??//new?line ????extern?CString?GetExePath();??????BOOL?WINAPI?Get_Module_By_Ret_Addr(PBYTE?Ret_Addr,?PCHAR?Module_Name,?PBYTE?&?Module_Addr)??????????{??????MODULEENTRY32???M?=?{sizeof(M)};??????HANDLE??hSnapshot;????????Module_Name[0]?=?0;????????????if?(CreateToolhelp32Snapshot_)??????{??????????hSnapshot?=?CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE,?0);????????????????????if?((hSnapshot?!=?INVALID_HANDLE_VALUE)?&&??????????????Module32First_(hSnapshot,?&M))??????????{??????????????do??????????????{??????????????????if?(DWORD(Ret_Addr?-?M.modBaseAddr)?<?M.modBaseSize)??????????????????{??????????????????????lstrcpyn(Module_Name,?M.szExePath,?MAX_PATH);??????????????????????Module_Addr?=?M.modBaseAddr;??????????????????????break;??????????????????}??????????????}?while?(Module32Next_(hSnapshot,?&M));??????????}????????????CloseHandle(hSnapshot);??????}????????return?!!Module_Name[0];??}???????int?WINAPI?Get_Call_Stack(PEXCEPTION_POINTERS?pException,?PCHAR?Str)??????????{??????CHAR????Module_Name[MAX_PATH];??????PBYTE???Module_Addr?=?0;??????PBYTE???Module_Addr_1;??????int?????Str_Len;????????????typedef?struct?STACK??????{??????????STACK?*?Ebp;??????????PBYTE???Ret_Addr;??????????DWORD???Param[0];??????}?STACK,?*?PSTACK;????????STACK???Stack?=?{0,?0};??????PSTACK??Ebp;????????if?(pException)???????????{??????????Stack.Ebp?=?(PSTACK)pException->ContextRecord->Ebp;??????????Stack.Ret_Addr?=?(PBYTE)pException->ExceptionRecord->ExceptionAddress;??????????Ebp?=?&Stack;??????}??????else??????{??????????Ebp?=?(PSTACK)&pException?-?1;????????????????????????if?(!IsBadReadPtr(Ebp,?sizeof(PSTACK)))??????????????Ebp?=?Ebp->Ebp;????????????}????????Str[0]?=?0;??????Str_Len?=?0;????????????????????for?(int?Ret_Addr_I?=?0;??????????(Ret_Addr_I?<?CALL_TRACE_MAX)?&&?!IsBadReadPtr(Ebp,?sizeof(PSTACK))?&&?!IsBadCodePtr(FARPROC(Ebp->Ret_Addr));??????????Ret_Addr_I++,?Ebp?=?Ebp->Ebp)??????{????????????????????if?(Get_Module_By_Ret_Addr(Ebp->Ret_Addr,?Module_Name,?Module_Addr_1))??????????{??????????????if?(Module_Addr_1?!=?Module_Addr)?????????????????{????????????????????????????????????Module_Addr?=?Module_Addr_1;??????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"%08X??%s",?Module_Addr,?Module_Name);??????????????}??????????????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,??????????????????NL?"??+%08X",?Ebp->Ret_Addr?-?Module_Addr);??????????????????????????????if?(pException?&&?!Ret_Addr_I)????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?"??Exception?Offset");??????????????else?if?(!IsBadReadPtr(Ebp,?sizeof(PSTACK)?+?5?*?sizeof(DWORD)))??????????????{??????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?"??(%X,?%X,?%X,?%X,?%X)",??????????????????????Ebp->Param[0],?Ebp->Param[1],?Ebp->Param[2],?Ebp->Param[3],?Ebp->Param[4]);??????????????}??????????}??????????else??????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"%08X",?Ebp->Ret_Addr);??????}????????return?Str_Len;??}???????int?WINAPI?Get_Version_Str(PCHAR?Str)??????{??????OSVERSIONINFOEX?V?=?{sizeof(OSVERSIONINFOEX)};??????????if?(!GetVersionEx((POSVERSIONINFO)&V))??????{??????????ZeroMemory(&V,?sizeof(V));??????????V.dwOSVersionInfoSize?=?sizeof(OSVERSIONINFO);??????????GetVersionEx((POSVERSIONINFO)&V);??????}????????if?(V.dwPlatformId?!=?VER_PLATFORM_WIN32_NT)??????????V.dwBuildNumber?=?LOWORD(V.dwBuildNumber);??????????return?wsprintf(Str,??????????NL?"Windows:??%d.%d.%d,?SP?%d.%d,?Product?Type?%d",???????????V.dwMajorVersion,?V.dwMinorVersion,?V.dwBuildNumber,?V.wServicePackMajor,?V.wServicePackMinor/*,?V.wProductType*/);??}???????PCHAR?WINAPI?Get_Exception_Info(PEXCEPTION_POINTERS?pException)??????{??????PCHAR???????Str;??????int?????????Str_Len;??????int?????????i;??????CHAR????????Module_Name[MAX_PATH];??????PBYTE???????Module_Addr;??????HANDLE??????hFile;??????FILETIME????Last_Write_Time;??????FILETIME????Local_File_Time;??????SYSTEMTIME??T;????????????Str?=?new?CHAR[DUMP_SIZE_MAX];????????if?(!Str)??????????return?NULL;????????Str_Len?=?0;??????Str_Len?+=?Get_Version_Str(Str?+?Str_Len);????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"Process:??");??????GetModuleFileName(NULL,?Str?+?Str_Len,?MAX_PATH);??????Str_Len?=?lstrlen(Str);??????????????if?(pException)??????{??????????EXCEPTION_RECORD?&??E?=?*pException->ExceptionRecord;??????????CONTEXT?&???????????C?=?*pException->ContextRecord;??????????????????????if?(Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress,?Module_Name,?Module_Addr))??????????{??????????????Str_Len?+=?wsprintf(Str?+?Str_Len,??????????????????NL?"Module:??%s",?Module_Name);????????????????if?((hFile?=?CreateFile(Module_Name,?GENERIC_READ,?FILE_SHARE_READ,?NULL,?OPEN_EXISTING,??????????????????FILE_ATTRIBUTE_NORMAL,?NULL))?!=?INVALID_HANDLE_VALUE)??????????????{??????????????????if?(GetFileTime(hFile,?NULL,?NULL,?&Last_Write_Time))??????????????????{??????????????????????FileTimeToLocalFileTime(&Last_Write_Time,?&Local_File_Time);??????????????????????FileTimeToSystemTime(&Local_File_Time,?&T);????????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,??????????????????????????NL?"Date?Modified:??%02d/%02d/%d",??????????????????????????T.wMonth,?T.wDay,?T.wYear);??????????????????}??????????????????CloseHandle(hFile);??????????????}??????????}??????????else??????????{??????????????Str_Len?+=?wsprintf(Str?+?Str_Len,??????????????????NL?"Exception?Addr:??%08X",?E.ExceptionAddress);??????????}????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,??????????????NL?"Exception?Code:??%08X",?E.ExceptionCode);????????????????????if?(E.ExceptionCode?==?EXCEPTION_ACCESS_VIOLATION)??????????{????????????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,??????????????????NL?"%s?Address:??%08X",??????????????????(E.ExceptionInformation[0])???"Write"?:?"Read",?E.ExceptionInformation[1]);??????????}??????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"Instruction:?");??????????for?(i?=?0;?i?<?16;?i++)??????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?"?%02X",?PBYTE(E.ExceptionAddress)[i]);??????????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"Registers:");??????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"EAX:?%08X??EBX:?%08X??ECX:?%08X??EDX:?%08X",?C.Eax,?C.Ebx,?C.Ecx,?C.Edx);??????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"ESI:?%08X??EDI:?%08X??ESP:?%08X??EBP:?%08X",?C.Esi,?C.Edi,?C.Esp,?C.Ebp);??????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"EIP:?%08X??EFlags:?%08X",?C.Eip,?C.EFlags);??????}???????????????????Str_Len?+=?wsprintf(Str?+?Str_Len,?NL?"Call?Stack:");??????Get_Call_Stack(pException,?Str?+?Str_Len);????????if?(Str[0]?==?NL[0])??????????lstrcpy(Str,?Str?+?sizeof(NL)?-?1);????????return?Str;??}???????void?WINAPI?Create_Dump(PEXCEPTION_POINTERS?pException,?BOOL?File_Flag,?BOOL?Show_Flag)????????????{??????HANDLE??hDump_File;??????PCHAR???Str;??????DWORD???Bytes;??????DWORD???nLen?=?0;????????CString?strDir,strTXTFile,strDMPFile;??????CString?strDate,strTotal;??????CTime???tm?=?CTime::GetCurrentTime();????????????strDir.Format(_T("%s\\Log"),GetExePath());??????strTXTFile.Format(_T("%s\\Log\\%04d-%02d-%02d?%02d%02d%02d.txt"),GetExePath(),tm.GetYear(),tm.GetMonth(),??????????tm.GetDay(),tm.GetHour(),tm.GetMinute(),tm.GetSecond());??????strDMPFile.Format(_T("%s\\Log\\%04d-%02d-%02d?%02d%02d%02d.dmp"),GetExePath(),tm.GetYear(),tm.GetMonth(),??????????tm.GetDay(),tm.GetHour(),tm.GetMinute(),tm.GetSecond());????????if(!PathFileExists(strDir))??????????CreateDirectory(strDir,NULL);????????Str?=?Get_Exception_Info(pException);??????????????????????if?(File_Flag)??????{??????????if?(Str)??????????{??????????????hDump_File?=?CreateFile(strTXTFile,??????????????????GENERIC_WRITE,?0,?NULL,?CREATE_ALWAYS,?FILE_ATTRIBUTE_NORMAL,?NULL);????????????????????????????nLen?=?lstrlen(Str);??????????????Str[nLen]?=?'\0';????????????????WriteFile(hDump_File,?Str,?lstrlen(Str)?+?1,?&Bytes,?NULL);????????????????CloseHandle(hDump_File);??????????}??????????????????????if?(MiniDumpWriteDump_)??????????{??????????????MINIDUMP_EXCEPTION_INFORMATION??M;????????????????M.ThreadId?=?GetCurrentThreadId();??????????????M.ExceptionPointers?=?pException;??????????????M.ClientPointers?=?0;????????????????hDump_File?=?CreateFile(strDMPFile,??????????????????GENERIC_WRITE,?0,?NULL,?CREATE_ALWAYS,?FILE_ATTRIBUTE_NORMAL,?NULL);????????????????MiniDumpWriteDump_(GetCurrentProcess(),?GetCurrentProcessId(),?hDump_File,??????????????????MiniDumpNormal,?(pException)???&M?:?NULL,?NULL,?NULL);????????????????CloseHandle(hDump_File);??????????}??????}?????????delete?Str;??}???/* Author: Vladimir Sedach. Purpose: demo of Call Stack creation by our own means, and with MiniDumpWriteDump() function of DbgHelp.dll. */ #include "StdAfx.h" #include "MiniDump.h" #include <Shlwapi.h> #pragma comment(lib,"shlwapi.lib") HMODULE hDbgHelp; MINIDUMP_WRITE_DUMP MiniDumpWriteDump_; CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_; MODULE32_FIRST Module32First_; MODULE32_NEST Module32Next_; #define DUMP_SIZE_MAX 8000 //max size of our dump #define CALL_TRACE_MAX ((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40)) //max number of traced calls #define NL "\r\n" //new line extern CString GetExePath(); //**************************************************************************************** BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, PCHAR Module_Name, PBYTE & Module_Addr) //**************************************************************************************** // Find module by Ret_Addr (address in the module). // Return Module_Name (full path) and Module_Addr (start address). // Return TRUE if found. { MODULEENTRY32 M = {sizeof(M)}; HANDLE hSnapshot; Module_Name[0] = 0; if (CreateToolhelp32Snapshot_) { hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0); if ((hSnapshot != INVALID_HANDLE_VALUE) && Module32First_(hSnapshot, &M)) { do { if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) { lstrcpyn(Module_Name, M.szExePath, MAX_PATH); Module_Addr = M.modBaseAddr; break; } } while (Module32Next_(hSnapshot, &M)); } CloseHandle(hSnapshot); } return !!Module_Name[0]; } //Get_Module_By_Ret_Addr //****************************************************************** int WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, PCHAR Str) //****************************************************************** // Fill Str with call stack info. // pException can be either GetExceptionInformation() or NULL. // If pException = NULL - get current call stack. { CHAR Module_Name[MAX_PATH]; PBYTE Module_Addr = 0; PBYTE Module_Addr_1; int Str_Len; typedef struct STACK { STACK * Ebp; PBYTE Ret_Addr; DWORD Param[0]; } STACK, * PSTACK; STACK Stack = {0, 0}; PSTACK Ebp; if (pException) //fake frame for exception address { Stack.Ebp = (PSTACK)pException->ContextRecord->Ebp; Stack.Ret_Addr = (PBYTE)pException->ExceptionRecord->ExceptionAddress; Ebp = &Stack; } else { Ebp = (PSTACK)&pException - 1; //frame addr of Get_Call_Stack() // Skip frame of Get_Call_Stack(). if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) Ebp = Ebp->Ebp; //caller ebp } Str[0] = 0; Str_Len = 0; // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. // Break trace on wrong stack frame. for (int Ret_Addr_I = 0; (Ret_Addr_I < CALL_TRACE_MAX) && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); Ret_Addr_I++, Ebp = Ebp->Ebp) { // If module with Ebp->Ret_Addr found. if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr_1)) { if (Module_Addr_1 != Module_Addr) //new module { // Save module's address and full path. Module_Addr = Module_Addr_1; Str_Len += wsprintf(Str + Str_Len, NL "%08X %s", Module_Addr, Module_Name); } // Save call offset. Str_Len += wsprintf(Str + Str_Len, NL " +%08X", Ebp->Ret_Addr - Module_Addr); // Save 5 params of the call. We don't know the real number of params. if (pException && !Ret_Addr_I) //fake frame for exception address Str_Len += wsprintf(Str + Str_Len, " Exception Offset"); else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) { Str_Len += wsprintf(Str + Str_Len, " (%X, %X, %X, %X, %X)", Ebp->Param[0], Ebp->Param[1], Ebp->Param[2], Ebp->Param[3], Ebp->Param[4]); } } else Str_Len += wsprintf(Str + Str_Len, NL "%08X", Ebp->Ret_Addr); } return Str_Len; } //Get_Call_Stack //*********************************** int WINAPI Get_Version_Str(PCHAR Str) //*********************************** // Fill Str with Windows version. { OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later if (!GetVersionEx((POSVERSIONINFO)&V)) { ZeroMemory(&V, sizeof(V)); V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx((POSVERSIONINFO)&V); } if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx return wsprintf(Str, NL "Windows: %d.%d.%d, SP %d.%d, Product Type %d", //SP - service pack, Product Type - VER_NT_WORKSTATION,... V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor/*, V.wProductType*/); } //Get_Version_Str //************************************************************* PCHAR WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) //************************************************************* // Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. { PCHAR Str; int Str_Len; int i; CHAR Module_Name[MAX_PATH]; PBYTE Module_Addr; HANDLE hFile; FILETIME Last_Write_Time; FILETIME Local_File_Time; SYSTEMTIME T; Str = new CHAR[DUMP_SIZE_MAX]; if (!Str) return NULL; Str_Len = 0; Str_Len += Get_Version_Str(Str + Str_Len); Str_Len += wsprintf(Str + Str_Len, NL "Process: "); GetModuleFileName(NULL, Str + Str_Len, MAX_PATH); Str_Len = lstrlen(Str); // If exception occurred. if (pException) { EXCEPTION_RECORD & E = *pException->ExceptionRecord; CONTEXT & C = *pException->ContextRecord; // If module with E.ExceptionAddress found - save its path and date. if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) { Str_Len += wsprintf(Str + Str_Len, NL "Module: %s", Module_Name); if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) { FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); FileTimeToSystemTime(&Local_File_Time, &T); Str_Len += wsprintf(Str + Str_Len, NL "Date Modified: %02d/%02d/%d", T.wMonth, T.wDay, T.wYear); } CloseHandle(hFile); } } else { Str_Len += wsprintf(Str + Str_Len, NL "Exception Addr: %08X", E.ExceptionAddress); } Str_Len += wsprintf(Str + Str_Len, NL "Exception Code: %08X", E.ExceptionCode); if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { // Access violation type - Write/Read. Str_Len += wsprintf(Str + Str_Len, NL "%s Address: %08X", (E.ExceptionInformation[0]) ? "Write" : "Read", E.ExceptionInformation[1]); } // Save instruction that caused exception. Str_Len += wsprintf(Str + Str_Len, NL "Instruction: "); for (i = 0; i < 16; i++) Str_Len += wsprintf(Str + Str_Len, " %02X", PBYTE(E.ExceptionAddress)[i]); // Save registers at exception. Str_Len += wsprintf(Str + Str_Len, NL "Registers:"); Str_Len += wsprintf(Str + Str_Len, NL "EAX: %08X EBX: %08X ECX: %08X EDX: %08X", C.Eax, C.Ebx, C.Ecx, C.Edx); Str_Len += wsprintf(Str + Str_Len, NL "ESI: %08X EDI: %08X ESP: %08X EBP: %08X", C.Esi, C.Edi, C.Esp, C.Ebp); Str_Len += wsprintf(Str + Str_Len, NL "EIP: %08X EFlags: %08X", C.Eip, C.EFlags); } //if (pException) // Save call stack info. Str_Len += wsprintf(Str + Str_Len, NL "Call Stack:"); Get_Call_Stack(pException, Str + Str_Len); if (Str[0] == NL[0]) lstrcpy(Str, Str + sizeof(NL) - 1); return Str; } //Get_Exception_Info //************************************************************************************* void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag) //************************************************************************************* // Create dump. // pException can be either GetExceptionInformation() or NULL. // If File_Flag = TRUE - write dump files (.dmz and .dmp) with the name of the current process. // If Show_Flag = TRUE - show message with Get_Exception_Info() dump. { HANDLE hDump_File; PCHAR Str; DWORD Bytes; DWORD nLen = 0; CString strDir,strTXTFile,strDMPFile; CString strDate,strTotal; CTime tm = CTime::GetCurrentTime(); strDir.Format(_T("%s\\Log"),GetExePath()); strTXTFile.Format(_T("%s\\Log\\%04d-%02d-%02d %02d%02d%02d.txt"),GetExePath(),tm.GetYear(),tm.GetMonth(), tm.GetDay(),tm.GetHour(),tm.GetMinute(),tm.GetSecond()); strDMPFile.Format(_T("%s\\Log\\%04d-%02d-%02d %02d%02d%02d.dmp"),GetExePath(),tm.GetYear(),tm.GetMonth(), tm.GetDay(),tm.GetHour(),tm.GetMinute(),tm.GetSecond()); if(!PathFileExists(strDir)) CreateDirectory(strDir,NULL); Str = Get_Exception_Info(pException); //if (Show_Flag && Str) // MessageBox(NULL, Str, "MiniDump", MB_ICONHAND | MB_OK); if (File_Flag) { if (Str) { hDump_File = CreateFile(strTXTFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); nLen = lstrlen(Str); Str[nLen] = '\0'; WriteFile(hDump_File, Str, lstrlen(Str) + 1, &Bytes, NULL); CloseHandle(hDump_File); } // If MiniDumpWriteDump() of DbgHelp.dll available. if (MiniDumpWriteDump_) { MINIDUMP_EXCEPTION_INFORMATION M; M.ThreadId = GetCurrentThreadId(); M.ExceptionPointers = pException; M.ClientPointers = 0; hDump_File = CreateFile(strDMPFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); MiniDumpWriteDump_(GetCurrentProcess(), GetCurrentProcessId(), hDump_File, MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL); CloseHandle(hDump_File); } } //if (File_Flag) delete Str; } //Create_Dump
具體參考方法如下:
1、在CXXDlg::OnInitDialog()中添加這樣一段:
?
[cpp] view plaincopyprint? SetUnhandledExceptionFilter(CrashReportEx);??HMODULE?hKernel32;??????hDbgHelp?=?LoadLibrary("DBGHELP.DLL");??MiniDumpWriteDump_?=?(MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp,?"MiniDumpWriteDump");????????hKernel32?=?GetModuleHandle("KERNEL32");??CreateToolhelp32Snapshot_?=?(CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32,?"CreateToolhelp32Snapshot");??Module32First_?=?(MODULE32_FIRST)GetProcAddress(hKernel32,?"Module32First");??Module32Next_?=?(MODULE32_NEST)GetProcAddress(hKernel32,?"Module32Next");?? SetUnhandledExceptionFilter(CrashReportEx); HMODULE hKernel32; // Try to get MiniDumpWriteDump() address. hDbgHelp = LoadLibrary("DBGHELP.DLL"); MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); // d("hDbgHelp=%X, MiniDumpWriteDump_=%X", hDbgHelp, MiniDumpWriteDump_); // Try to get Tool Help library functions. hKernel32 = GetModuleHandle("KERNEL32"); CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32First"); Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32Next");
?
測試代碼如下:
?
[cpp] view plaincopyprint? class?CTestDlg?:?public?CDialog??{????public:??????CTestDlg(CWnd*?pParent?=?NULL);?????????void?Fun1(char?*pszBuffer);??????void?Fun2(char?*pszBuffer);??????void?Fun3(char?*pszBuffer);??};??class CTestDlg : public CDialog { // Construction public: CTestDlg(CWnd* pParent = NULL); // standard constructor void Fun1(char *pszBuffer); void Fun2(char *pszBuffer); void Fun3(char *pszBuffer); };
[cpp] view plaincopyprint? void?CTestDlg::Fun1(char?*pszBuffer)??{??????Fun2(pszBuffer);??}????void?CTestDlg::Fun2(char?*pszBuffer)??{??????Fun3(pszBuffer);??}????void?CTestDlg::Fun3(char?*pszBuffer)??{??????pszBuffer[1]?=?0x00;??}??void CTestDlg::Fun1(char *pszBuffer) { Fun2(pszBuffer); } void CTestDlg::Fun2(char *pszBuffer) { Fun3(pszBuffer); } void CTestDlg::Fun3(char *pszBuffer) { pszBuffer[1] = 0x00; }
我們?cè)陔p擊確定按鈕時(shí)的響應(yīng)代碼如下:
?
?
[cpp] view plaincopyprint? void?CTestDlg::OnOK()???{????????????Fun1(NULL);??}??void CTestDlg::OnOK() { // TODO: Add extra validation here Fun1(NULL); }
2、設(shè)置VC編譯選項(xiàng),勾選生成MAP和Debug Info:
3、將編譯生成的Release目錄中的pdb、map文件保存起來,以后調(diào)試會(huì)用到:
4、運(yùn)行程序,單擊確定按鈕出現(xiàn)異常后自動(dòng)重啟,并創(chuàng)建一個(gè)Log文件夾,里面生成dump文件:
5、我們打開WinDbg,設(shè)置一下pdb路徑(File \ Symbol File Path):
6、用WiinDbg打開dump文件(File \ Open Crash Dump)
7、輸入命令!analyze -v,等待幾秒后會(huì)打印出錯(cuò)誤信息,函數(shù)調(diào)用棧如下圖:
OK ,這樣我們就能在發(fā)布版本的程序中,準(zhǔn)確的定位到哪個(gè)函數(shù)出了問題,所以發(fā)布程序時(shí),一定要記得生成pdb、map文件,不然客戶運(yùn)行出錯(cuò)的話,你不死也殘!
測試工程下載地址:
http://download.csdn.net/source/3575167
轉(zhuǎn)載于:https://www.cnblogs.com/gxh973121/archive/2012/03/14/2395397.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的[调试技巧] 如何利用WinDbg找出程序崩溃的位置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。