寫程序的人都有這個苦惱,用戶說你的程序總有時會莫名奇妙的崩潰,可是你怎么也無法重現(xiàn)崩潰的場景,所以也無法找出程序中的Bug,難道就束手無策嗎?
??? 前幾天在一本雜志(《程序員-游戲創(chuàng)造》)上看到一篇關(guān)于這個主題的文章,非常詳細(xì)的論述了怎樣通過代碼和工具實現(xiàn)Bug Report,使得你可以快速定位崩潰的源代碼行數(shù)。
?
??? 要catch未處理的異常,該文中論述了使用全局的try-catch的優(yōu)缺點(diǎn),全局的try-catch導(dǎo)致了調(diào)試工作的麻煩,不可取。Win32異常的可以通過設(shè)置過濾函數(shù)SetUnhandledExceptionFilter來處理,而C++也有set_terminate函數(shù)可以設(shè)置一個函數(shù)來處理任何未catch的異常。
?
?? 文章還告訴我們,main/WinMain是程序的入口處,但靜態(tài)初始化在這之前進(jìn)行,操作系統(tǒng)裝載我們的程序后,先調(diào)用的是CRT提供函數(shù)WinMainCRTStartup/mainCRTStartup,可以通過VC開發(fā)工具設(shè)置程序的入口函數(shù)來獲取異常的優(yōu)先控制權(quán)(/ENTRY:函數(shù))(Linker->Advanced->Entry Point)。
??? 1.用minidump進(jìn)行調(diào)試
??? 這個技術(shù)是改進(jìn)Windows操作系統(tǒng)的錯誤報告機(jī)制的關(guān)鍵。產(chǎn)生的文件非常小,適合于網(wǎng)絡(luò)傳輸。???? 有三種方法創(chuàng)建一個minidump文件:???? a. 在你的應(yīng)用程序中加入未處理的exception處理函數(shù),函數(shù)中創(chuàng)建minidump文件???? b. Visual Studio .NET集成開發(fā)環(huán)境中調(diào)試時,Debug菜單中按Save Dump???? c. Windows XP 在一個程序遇到未處理的異常時會自動產(chǎn)生minidump文件,但直接提交給微軟,你沒機(jī)會處理。
??? 要使用該技術(shù),build的時候要生成完全的調(diào)試信息文件(PDB),發(fā)布每個版本時要保存每個可執(zhí)行文件(exe/dll)以及相對應(yīng)的pdb文件,以備將來debug用。為了更好的輔助文件匹配,注意要正確設(shè)置每個可執(zhí)行文件的內(nèi)部版本號,每次發(fā)布要使用不同的版本號,然而debugger使用的是PE文件頭中內(nèi)部時間蹉來匹配的。在發(fā)布版本中生成調(diào)試信息有副作用,占用更多空間并且容易被逆向工程。
??? 寫minidump的API是MiniDumpWriteDump,在PlatformSDK中的DBGHelp.dll,只有XP版本的沒有問題。為了調(diào)用這個API,你必須使用SetUnhandledExceptionFilter API來設(shè)置一個未處理異常處理器,用來catch崩潰,但在VS2005之前,仍然會無法catch純C++異常。
??? 在你的函數(shù)中,注意要導(dǎo)入正確的DbgHelp.dll,使用LoadLibrary會默認(rèn)載入System32目錄下的dll,Win2000將會導(dǎo)致錯誤。
??? 分析用戶傳回的minidump文件,使用Visual Studio .Net打開(*.dmp,*.mdmp)并創(chuàng)建缺省的項目。按F5在Output窗口中顯示載入的模塊信息。重建所有進(jìn)程狀態(tài),但可能缺少symbols以及調(diào)試信息。所以你需要所有匹配的exe和dll文件以及pdb文件,要查看所有的module打開Modules窗口,找出所有(通常沒必要所有)匹配的dll(DLL Help database: http://support.microsoft.com/servicedesks/fileversion/dllinfo.asp.),或者你需要操作系統(tǒng)的安裝盤或者從報告者的系統(tǒng)中得到所有匹配的dll,拷貝到本地的一個目錄下,例如D:\Mudules。然后設(shè)置項目的Debugging頁中的Command參數(shù)為MODPATH=D:\Mudules,按F5重新載入minidump。注意你也需要每個dll匹配的pdb文件,平臺的可以在操作系統(tǒng)安裝盤或者
http://www.microsoft.com/ddk/debugging中找到。
?Operating system? Files required? Windows NT 4???????? DBGs? Windows 2000???????? DBGs, PDBs? Windows XP??????????? PDBs?????? 如果你要處理很多minidumps,可能需要所有的dll和pdb/dbg,這時你可以使用Symbol Server來管理所有資源,首先到
http://www.microsoft.com/ddk/debugging/symbols.asp下載調(diào)試工具,拷貝Symsrv.dll到VS.Net可以訪問的地方,建一個本地目錄,例如:C:\localstore,在項目屬性對話框中設(shè)置Debugging頁中Symbol路徑為SRV*c:/localstore*http://msdl.microsoft.com/download/symbols。此后,每次F5后就會自動下載必要的文件。
??? 原文:http://www.codeproject.com/debug/postmortemdebug_standalone1.asp???? 例子:http://www.codeproject.com/debug/crash_report.asp
??? 2. map文件???? 生成map文件來定位崩潰的代碼行???? 原文:http://www.codeproject.com/debug/mapfile.asp???????? 3. CrashFinder
??? John Robbins 寫好的CrashFinder能夠發(fā)現(xiàn)VC++/VB的應(yīng)用程序的崩潰處(代碼行)。Release版本也要生成Debug信息,在VC中使用/Zi 編譯選項(C/C++ tab中Program Database )和/DEBUG and /PDB:<pdb filename>鏈接選項(Link tab中打勾Debug info 并選擇Microsoft format),VB中在項目屬性打勾Compile to Native Code 和Create Symbolic Debug Info 選項。
??? 如果你在Debugger的OUtput窗口中看到LDR: Dll xxx base 10000000 relocated due to collision with yyy信息,可以通過REBASE.EXE(Platform SDK)程序使得你可以重新安排載入dll/ocx地址,因為不同的系統(tǒng)載入dll/ocx的地址不同,如果沖突會導(dǎo)致你找不出到底是哪個dll崩潰。
??? 如果是beta版,你可以讓應(yīng)用程序生成詳細(xì)Dr. Watson 信息(要很大空間不適合傳輸),你可以在安裝應(yīng)用程序時檢測系統(tǒng)是否已經(jīng)安裝Dr. Watson(在注冊表HKEY_LOCAL_MACHINE\SOFTWARE\ Microsoft\Windows NT\CurrentVersion\AeDebug 處),有了這種信息你可以得到詳細(xì)的堆??臻g并游刃有余地找出崩潰的地方。
??? CrashFinder使用IMAGEHLP.DLL符號引擎(Windows NT? 4.0首次引入),Windows NT 5.0 SDK已經(jīng)可以處理源碼行號。(CrashFinder2.1已經(jīng)升級,使用最新的DBGHelp.dll)
??? CrashFinder只保存應(yīng)用程序和調(diào)試信息文件的目錄信息,所以無需每次編譯都需要CrashFinder連編。你可以創(chuàng)建多個CrashFinder項目,每個項目針對一種操作系統(tǒng)。
??? 原文:http://www.microsoft.com/msj/0498/bugslayer0498.aspx???? 下載:http://www.wintellect.com/about/instructors/robbins/code.aspx
?
??? 解決方案:
??? (To be continue)
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=658660
文章出處:飛諾網(wǎng)(www.firnow.com):http://dev.firnow.com/course/3_program/c++/cppjs/200876/130580.html
posted on 2010-10-11 09:31
我風(fēng) 閱讀(864)
評論(0) 編輯 收藏 引用