I met a few friends in the Forum, saying that the program crashes from time to time and what xxoo cannot be read! If this memory address is used, you may lose your mind ~~
So let's share some basic debugging skills. The tools that need to be prepared include windbg + vc6.0,
Below is a self-organized copy of the source code that automatically generates the dump file. You only need to add it to the project. The source code is as follows:
Minidump. h
#include <windows.h>#include <tlhelp32.h>//#include "dbghelp.h"//#define DEBUG_DPRINTF1//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 {DWORDThreadId;PEXCEPTION_POINTERSExceptionPointers;BOOLClientPointers;} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;typedef enum _MINIDUMP_TYPE {MiniDumpNormal =0x00000000,MiniDumpWithDataSegs =0x00000001,} MINIDUMP_TYPE;typedefBOOL (WINAPI * MINIDUMP_WRITE_DUMP)(IN HANDLEhProcess,IN DWORDProcessId,IN HANDLEhFile,IN MINIDUMP_TYPEDumpType,IN CONST PMINIDUMP_EXCEPTION_INFORMATIONExceptionParam, OPTIONALIN PVOIDUserStreamParam, OPTIONALIN PVOIDCallbackParam OPTIONAL);#elsetypedefBOOL (WINAPI * MINIDUMP_WRITE_DUMP)(IN HANDLEhProcess,IN DWORDProcessId,IN HANDLEhFile,IN MINIDUMP_TYPEDumpType,IN CONST PMINIDUMP_EXCEPTION_INFORMATIONExceptionParam, OPTIONALIN PMINIDUMP_USER_STREAM_INFORMATIONUserStreamParam, OPTIONALIN PMINIDUMP_CALLBACK_INFORMATIONCallbackParam OPTIONAL);#endif //#ifndef _DBGHELP_// Tool Help functions.typedefHANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);typedefBOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);typedefBOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);extern void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag);extern HMODULEhDbgHelp;extern MINIDUMP_WRITE_DUMPMiniDumpWriteDump_;extern CREATE_TOOL_HELP32_SNAPSHOTCreateToolhelp32Snapshot_;extern MODULE32_FIRSTModule32First_;extern MODULE32_NESTModule32Next_;
Minidump. cpp
/*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")HMODULEhDbgHelp;MINIDUMP_WRITE_DUMPMiniDumpWriteDump_;CREATE_TOOL_HELP32_SNAPSHOTCreateToolhelp32Snapshot_;MODULE32_FIRSTModule32First_;MODULE32_NESTModule32Next_;#defineDUMP_SIZE_MAX8000//max size of our dump#defineCALL_TRACE_MAX((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40))//max number of traced calls#defineNL"\r\n"//new lineextern 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.{MODULEENTRY32M = {sizeof(M)};HANDLEhSnapshot;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.{CHARModule_Name[MAX_PATH];PBYTEModule_Addr = 0;PBYTEModule_Addr_1;intStr_Len;typedef struct STACK{STACK *Ebp;PBYTERet_Addr;DWORDParam[0];} STACK, * PSTACK;STACKStack = {0, 0};PSTACKEbp;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 addressStr_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]);}}elseStr_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.{OSVERSIONINFOEXV = {sizeof(OSVERSIONINFOEX)};//EX for NT 5.0 and laterif (!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) = 0x04xxreturn 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.{PCHARStr;intStr_Len;inti;CHARModule_Name[MAX_PATH];PBYTEModule_Addr;HANDLEhFile;FILETIMELast_Write_Time;FILETIMELocal_File_Time;SYSTEMTIMET;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.{HANDLEhDump_File;PCHARStr;DWORDBytes;DWORDnLen = 0;CString strDir,strTXTFile,strDMPFile;CString strDate,strTotal;CTimetm = 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_INFORMATIONM;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
The specific reference method is as follows:
1. Add the following section to cxxdlg: oninitdialog:
SetUnhandledExceptionFilter(CrashReportEx);HMODULEhKernel32;// 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");
Test Project:
Http://download.csdn.net/source/3575167
For more information, go to the VC station: Use windbg to find the code line number of the program crash