C++記錄程式崩潰時的dumpfile
最近一段時間,新上線的軟體在外場偶爾會出現異常崩潰的情況。由於試用範圍比較分散,很難一一前往現場定位問題。而傳統的log日誌方法,在崩潰的情況下,並不能比較準確的表示出問題位置,這使得軟體除錯程式緩慢。
後在公司前輩的指點下,我們想到了使用window自帶的dumpfile來記錄崩潰時刻的堆疊資訊,這樣配合log日誌記錄,能夠快速的定位出問題點。大大提高了系統除錯效率。
經過一段時間的除錯,現在專案已相對穩定了。想記錄下此方法,以待後續類似情況下使用。
//使所有版本都可以捕獲到異常
void DisableSetUnhandledExceptionFilter()
{
void*addr=(void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")),"SetUnhandledExceptionFilter");
if(addr)
{
unsigned char code[16];
int size=0;
code[size++]=0x33;
code[size++]=0xC0;
code[size++]=0xC2;
code[size++]=0x04;
code[size++]=0x00;
DWORD dwOldFlag,dwTempFlag;
VirtualProtect(addr,size,PAGE_READWRITE,&dwOldFlag);
WriteProcessMemory(GetCurrentProcess(),addr,code,size,NULL);
VirtualProtect(addr,size,dwOldFlag,&dwTempFlag);
}
}
//程式未捕獲的異常處理函式
LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS*ExceptionInfo)
{
::AfxMessageBox("ExceptionFilter");
HANDLE hFile=::CreateFile(_T("C:dumpfile.dmp"),GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
MINIDUMP_EXCEPTION_INFORMATION einfo;
einfo.ThreadId=::GetCurrentThreadId();
einfo.ExceptionPointers=ExceptionInfo;
einfo.ClientPointers=FALSE;
::MiniDumpWriteDump(::GetCurrentProcess(),::GetCurrentProcessId(),hFile,MiniDumpWithFullMemory,&einfo,NULL,NULL);
::CloseHandle(hFile);
}
return 0;
}
//把當前時刻的執行緒棧記錄到DUMP檔案中
int RecordCurStack()
{
HANDLE hFile=::CreateFile(_T("C:dumpfile.dmp"),GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
::MiniDumpWriteDump(::GetCurrentProcess(),::GetCurrentProcessId(),hFile,MiniDumpWithFullMemory,NULL,NULL,NULL);
::CloseHandle(hFile);
return 1;
}
return 0;
}
bool bCreateDumpThrd=true;
//迴圈檢測執行緒
//檢視到有ADTV2_TEMP.TXT檔案,則記錄下當前時刻的堆疊
void CreateDumpThrd(void*pv)
{
HANDLE hFile;
string strPath=FileAssist::GetExePath()+"ADTV2_TEMP.TXT";
while(bCreateDumpThrd)
{
//每5秒檢測一次
Sleep(5000);
hFile=CreateFileA(strPath.c_str(),//file to open
GENERIC_READ,//open for reading
FILE_SHARE_READ,//share for reading
NULL,//default security
OPEN_EXISTING,//existing file only
FILE_ATTRIBUTE_NORMAL,//normal file
NULL);//no attr.template
if(hFile!=INVALID_HANDLE_VALUE)
{
//防止多次記錄當前堆疊資訊,刪除檔案
::CloseHandle(hFile);
::DeleteFile(strPath.c_str());
RecordCurStack();
}
}
}
然後在程式入口將異常處理介面宣告即可。
//除錯資訊
::SetUnhandledExceptionFilter(ExceptionFilter);//設定異常處理函式
DisableSetUnhandledExceptionFilter();//獲取未處理的異常
這樣,在程式異常時,就可以在C盤根目錄下記錄一個dumpfile.dmp的檔案。這個檔案會比較大,一般有100多M,其中資訊比log形式的日誌豐富很多,包括了異常時的堆疊呼叫關係以及各物件的值。,在VS中可以直接開啟。如果保留了和當時編譯軟體一致的程式碼備份的話,可以直接使用VS的debug功能定位到問題程式碼行,否則,debug定位是到彙編程式碼行,看起來比較麻煩。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69920910/viewspace-2734140/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 崩潰日記
- 記錄一個LifeCycle 多執行緒使用導致的崩潰執行緒
- 幽蘭核心崩潰自救記
- 記錄一次解決App崩潰問題的解決方案APP
- 記一次 .NET 某工控MES程式 崩潰分析
- Flutter: BottomNavigationBar + PageView 翻頁時崩潰FlutterNavigationView
- WWDC 2018:理解崩潰以及崩潰日誌
- app 崩潰的原因APP
- UE4 記憶體寫壞導致異常崩潰問題記錄記憶體
- memcopy 導致的程式碼崩潰問題,memcpy的三大踩坑記memcpy
- 讓 Chrome 崩潰的一行 CSS 程式碼ChromeCSS
- Qt程式繼承QApplication發生崩潰的原因QT繼承APP
- Android 收集程式崩潰異常資訊Android
- APP防崩潰APP
- IBM X3850伺服器崩潰資料恢復過程記錄IBM伺服器資料恢復
- 當初自學C++時的筆記記錄C++筆記
- Linux中程式崩潰及重啟的原因詳解!Linux
- 關於Mozilla崩潰的研究
- Go程式崩潰現場應該如何保留?Go
- 頁面崩潰了!記錄一次測試中出現的前端記憶體溢位現象前端記憶體溢位
- 記一次 .NET某工控 宇宙射線 導致程式崩潰分析
- 記一次 騰訊會議 的意外崩潰分析
- 記一次VMware的崩潰除錯分析過程除錯
- iOS Crash不崩潰iOS
- 崩潰的一天,西安一碼通崩潰背後的技術問題。
- 記一次Linux核心崩潰:kdump,crash,vmcoreLinux
- 執行緒崩潰為什麼不會導致 JVM 崩潰執行緒JVM
- 線上Redis-Docker叢集出現物理機崩潰的一次問題記錄RedisDocker
- 記錄線上APP一個排序比較引發的崩潰 Comparison method violates its general contract!APP排序
- 讓程式設計師人崩潰的 99個瞬間...程式設計師
- 史上最坑爹的程式碼!個個讓人崩潰!
- [轉載]程式設計師自由創業週記:我曾走在崩潰的邊緣程式設計師創業
- iOS | 零程式碼快速整合AGC崩潰服務iOSGC
- Android | 零程式碼快速整合AGC崩潰服務AndroidGC
- iOS開發的底線-崩潰iOS
- 記一次線上崩潰問題的排查過程
- IOS 崩潰日誌分析iOS
- MySQL 8.0.11 無故崩潰MySql