日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[调试技巧] 如何利用WinDbg找出程序崩溃的位置

發布時間:2025/4/16 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [调试技巧] 如何利用WinDbg找出程序崩溃的位置 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/wangningyu/article/details/6748138

?

之前碰到論壇里有幾個好友,說程序不時的崩潰,什么xxoo不能read的! 如果光要是這個內存地址,估計你會瘋掉~~

所以分享一下基本的調試技巧,需要準備的工具有WinDbg + VC6.0,

下面是自己整理的一份自動生成DUMP文件的源代碼,只需要添加到工程即可,源代碼如下:

MiniDump.h

?

[cpp] view plaincopyprint?
  • #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_;??
  • #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?
  • /*?
  • ????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??
  • /* 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;??
  • ??
  • //?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");??
  • 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??
  • {??
  • //?Construction ??
  • public:??
  • ????CTestDlg(CWnd*?pParent?=?NULL);?//?standard?constructor ??
  • ??
  • ????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; }
    我們在雙擊確定按鈕時的響應代碼如下:

    ?

    ?

    [cpp] view plaincopyprint?
  • void?CTestDlg::OnOK()???
  • {??
  • ????//?TODO:?Add?extra?validation?here ??
  • ????Fun1(NULL);??
  • }??
  • void CTestDlg::OnOK() { // TODO: Add extra validation here Fun1(NULL); }

    2、設置VC編譯選項,勾選生成MAP和Debug Info:



    3、將編譯生成的Release目錄中的pdb、map文件保存起來,以后調試會用到:

    4、運行程序,單擊確定按鈕出現異常后自動重啟,并創建一個Log文件夾,里面生成dump文件:

    5、我們打開WinDbg,設置一下pdb路徑(File \ Symbol File Path):

    6、用WiinDbg打開dump文件(File \ Open Crash Dump)

    7、輸入命令!analyze -v,等待幾秒后會打印出錯誤信息,函數調用棧如下圖:


    OK ,這樣我們就能在發布版本的程序中,準確的定位到哪個函數出了問題,所以發布程序時,一定要記得生成pdb、map文件,不然客戶運行出錯的話,你不死也殘!


    測試工程下載地址:

    http://download.csdn.net/source/3575167

    轉載于:https://www.cnblogs.com/gxh973121/archive/2012/03/14/2395397.html

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的[调试技巧] 如何利用WinDbg找出程序崩溃的位置的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。