1. 程式人生 > >VS2005(vs2008,vs2010)使用map檔案查詢程式崩潰原因

VS2005(vs2008,vs2010)使用map檔案查詢程式崩潰原因

一般程式崩潰可以通過debug,找到程式在那一行程式碼崩潰了,最近編一個多執行緒的程式,都不知道在那發生錯誤,多執行緒併發,又不好單行除錯,終於找到一個比較好的方法來找原因,通過生成map檔案,由於2005取消map檔案生成行號資訊(vc6.0下是可以生成行號資訊的,不知道microsoft怎麼想的,在2005上取消了),只能定位在那個函式發生崩潰。這裡可以通過生成cod檔案,即機器碼這一檔案,具體定位在那一行崩潰。 

首先配置vc2005生成map檔案和cod檔案: 
(1).map檔案:property->Configuration Properties->Linker->Debugging 中的Generate Map File選擇Yes(/MAP); 


(2).cod檔案:property->Configuration Properties->C/C++->output Files中Assembler OutPut中選擇Assembly,Maching Code and Source(/FAcs),生成機器,原始碼。 

上面所說的 property 是“專案”選單下的 property,而非“工具”選單下的 property。(轉者注) 

簡單例子:C++程式碼
#include "stdafx.h"     

void errorFun(int * p)
{
    *p=1;   
}     

int  _tmain(int argc, _TCHAR* argv[])   
{    
     int * p=NULL;    
     errorFun(p); 

     return 0; 
}

在errorFun中函式中,*p=1這一行出錯,由於p沒有申請空間,執行時出錯,彈出 
Unhandled exception at 0x004113b1 in testError.exe: 0xC0000005: Access violation writing location 0x00000000. 
在0x004113b1程式發生崩潰。 

具體步驟:
(1)debug檔案下開啟map檔案,定位崩潰函式. 

map檔案開頭是一些連結資訊,然後我們要找函式和實始地址資訊。地址是函始的開始地址 

Address       Publics by Value       Rva+Base    Lib:Object 



0000:00000000    ___safe_se_handler_count   00000000    <absolute> 
0000:00000000    ___safe_se_handler_table   00000000    <absolute> 
0000:00000000    ___ImageBase         00400000    <linker-defined> 
0001:00000000    __enc$textbss$begin      00401000     <linker-defined> 
0001:00010000    __enc$textbss$end       00411000     <linker-defined> 
0002:00000390    [email protected]@[email protected]    00411390 f    testError.obj
0002:000003d0    _wmain            004113d0 f    testError.obj 
0002:00000430    __RTC_InitBase        00411430 f   MSVCRTD:init.obj 
0002:00000470    __RTC_Shutdown        00411470 f   MSVCRTD:init.obj 
0002:00000490    __RTC_CheckEsp        00411490 f   MSVCRTD:stack.obj 
0002:000004c0    @[email protected]    004114c0 f   MSVCRTD:stack.obj 
0002:00000540    @_RTC_Al[email protected]     00411540 f    MSVCRTD:stack.obj 

.... 

程式崩潰地址0x004113b1,我們找到第一個比這個地址大的004113d0,前一個是00411390,地址是函式的開始地址,所以發生的崩潰的的函式是errorFun,這個函式的初始地址00411390. 

(2)找出具體崩潰行號. 

由(2)可知,發生錯誤函式是errorFun,在testError.obj,開啟testError.cod檔案,找到errorFun函式生成的機器碼. 

[email protected]@[email protected] PROC    ; errorFun, COMDAT 

; 7    : { 

  00000 55   push  ebp 
  00001 8b ec   mov  ebp, esp 
  00003 81 ec c0 00 00 
00   sub  esp, 192  ; 000000c0H 
  00009 53   push  ebx 
  0000a 56   push  esi 
  0000b 57   push  edi 
  0000c 8d bd 40 ff ff 
ff   lea  edi, DWORD PTR [ebp-192] 
  00012 b9 30 00 00 00  mov  ecx, 48   ; 00000030H 
  00017 b8 cc cc cc cc  mov  eax, -858993460  ; ccccccccH 
  0001c f3 ab   rep stosd 

; 8    :  *p=1; 

  0001e 8b 45 08  mov  eax, DWORD PTR _p$[ebp] 
  00021 c7 00 01 00 00 
00   mov  DWORD PTR [eax], 1 

; 9    : } 

  00027 5f   pop  edi 
  00028 5e   pop  esi 
  00029 5b   pop  ebx 
  0002a 8b e5   mov  esp, ebp 
  0002c 5d   pop  ebp 
  0002d c3   ret  0 
(說明: 7,8,9是表示在原始碼的行號。 
00000 55   push  ebp,000000是相對偏移地地,55是機器碼號,push ebp,000000是彙編碼。) 

通過(2)我們計算相對偏移地址,即崩潰地址-函式起始地址,0x004113b1-0x00411390=0x21(16進位制的計數)。找到0x21這一行對應的機器碼是 00021 c7 00 01 00 00,向上看它是由第8行*p=1;生成的彙編碼,由此可見是這一行程式發生崩潰。 


結束語:當然這只是一個簡單的例子,實際上一執行便知道是這一行出錯,但是對於一個比較大的工程,特別是在多執行緒併發情況下,要找出那一行出錯比較困難,便可以使用map和cod檔案找到程式崩潰原因。

補充:

讀了老羅的“僅通過崩潰地址找出原始碼的出錯行”(下稱"羅文")一文後,感覺該文還是可以學到不少東西的。不過文中尚存在有些說法不妥,以及有些操作太繁瑣的地方 。為此,本人在學習了此文後,在多次實驗實踐基礎上,把該文中的一些內容進行補充與改進,希望對大家除錯程式,尤其是release版本的程式有幫助 。歡迎各位朋友批評指正。

一、該方法適用的範圍

在windows程式中造成程式崩潰的原因很多,而文中所述的方法僅適用與:由一條語句當即引起的程式崩潰。如原文中舉的除數為零的崩潰例子。而筆者在實際工作中碰到更多的情況是:指標指向一非法地址 ,然後對指標的內容進行了,讀或寫的操作。例如:

1.void Crash1() 2.{ 3.char * p =(char*)100; 4.*p=100; 5.}

這些原因造成的崩潰,無論是debug版本,還是release版本的程式,使用該方法都可找到造成崩潰的函式或子程式中的語句行,具體方法的下面還會補充說明。 另外,實踐中另一種常見的造成程式崩潰的原因:函式或子程式中區域性變數陣列越界付值,造成函式或子程式返回地址遭覆蓋,從而造成函式或子程式返回時崩潰。例如:

01.#include 02.void Crash2(); 03.int main(int argc,char* argv[]) 04.{ 05.

相關推薦

VS2005(vs2008,vs2010)使用map檔案查詢程式崩潰原因

一般程式崩潰可以通過debug,找到程式在那一行程式碼崩潰了,最近編一個多執行緒的程式,都不知道在那發生錯誤,多執行緒併發,又不好單行除錯,終於找到一個比較好的方法來找原因,通過生成map檔案,由於2005取消map檔案生成行號資訊(vc6.0下是可以生成行號資訊的,不知

VS2005 vs2008 vs2010 除錯時打不了斷點總結

VS程式設計除錯時,偶爾會遇到打不了斷點的情況,根據一路下來的經驗,總結一下,以免以後遇到這種情況可以再參考下。(注:此文章相當於自己的學習筆記,以供自己今後參考,希望不要給各位帶來壞的示範,有錯誤請多指正) 本文截圖使用的VS軟體為VS2005,vs2008 2010等類

程式碼混淆導致程式崩潰原因分析

程式碼混淆是一種專案加密的方法,混淆後的類和方法會重新命名成a.a.b.c的形式,從而防止反編譯破解程式碼。 如果程式碼中使用了反射或者呼叫了JNI等底層程式碼,程式碼混淆會導致程式崩潰, 例如使用JSONObject.toJavaObject()方法將json轉化為物件時

windows程式崩潰時自動生成dump檔案方法

  /****************第一步新增createdump.h********************************* 新增一個頭檔案:createdump.h #pragma once #include <windows.h> #inclu

Winows下程式崩潰自動建立Dump檔案以方便跟蹤問題

首先定義一個預設的異常處理回撥函式: LONG CrashHandler(struct_EXCEPTION_POINTERS* pExceptionInfo) { std::string dumpFileName = "./CrashDump.dump"; H

windbg載入dmp檔案 跟蹤記憶體洩漏或程式崩潰位置 ntdll.pdb缺少

前提:將要除錯的exe 檔案,pdb檔案,dmp檔案拷貝到同一路徑下   E:\test_projects\ConsoleApplication3\Debug;srv*E:\test_projects\ConsoleApplication3\Debug*https://msdl.m

java 遇到未知異常使程式崩潰,輸出jvm的dump崩潰資訊到指定檔案,然後殺死此程序

1.我們首先需要獲取當前java程序的pid。方法為: //檢視當前程序pid private static void getPID(){ RuntimeMXBean runtime = ManagementFactory.ge

利用Windows自帶的功能當程式崩潰時產生崩潰轉儲檔案(dmp)

 何志丹 以管理員身份 執行 :OpenDump.bat 其本質是寫登錄檔。 執行後: 任何程式崩潰都會在C:\CrashDump 產生dmp檔案(比較大,約50到200M)。 至少在Win7、Win10的電腦,Win10的平板上執行正確。 OpenDump.bat @e

windows 應用程式崩潰時的記憶體轉儲及dump檔案的分析

1、在現場設定程式崩潰時的自動記憶體轉儲,得到dump檔案        在windows 登錄檔如下項:      //HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/CurrentVersion/AeDebug

生成程式崩潰的dump檔案,使用windbg除錯

1,目的 有時候程式在客戶那裡崩潰了,你程式也沒有什麼有效的log日誌能記錄到崩潰的細節,那這實在是一件很麻煩的事情。 你得向客戶反覆瞭解操作內容並希望能在自己這裡重現,這個過程想想都很痛苦吧。。 使用下面的方法,能在程式崩潰時生成一個自己的dump檔案,記錄了崩潰時的一

VS2008 新增高階儲存選項(vs2008,vs2010檔案選單下沒有高階儲存選項)

關於VS的選單——自定義 VS裡面的檔案下拉選單沒有高階儲存的選項: 解決方法: 首先點工具-自定義: 然後按下圖操作: 哈哈,不見的高階儲存選項選單回來啦: 當然,你可以將一些常用的功能按照上面那樣操作,拖放到工具欄中,例如: 呵呵,你可以開始打造你自己的VS的強大的工具欄了。

VS2003,VS2005,VS2008 低版本開啟高版本的解決方案和工程檔案

一、用記事本開啟sln檔案,將:  Microsoft Visual Studio Solution File, Format Version 10.00  # Visual Studio 2008  改成:  Microsoft Visual Studio Solution File, Format Ve

VS2010下使用dmp檔案和pdb檔案定位程式異常程式碼行號的注意事項

2018-01-12 建立人:Ruo_Xiao 2018-01-15 修改人:Ruo_Xiao 新增為dump、exe和pdb版本保持一致的原因。 一、minidump檔案 崩潰轉儲是建立一個應用程式崩潰瞬間的狀態映象。 初代的轉儲檔案是記錄了程序的虛擬

【轉】VS2008採用了新的程式部署技術(manifest清單檔案

vc2005/vc2008採用了新的程式部署技術(manifest清單檔案),manifest清單檔案實際上類似於我們常用的makefile檔案,它定義了程式執行的依賴關係(程式執行所需要的dll庫的名稱、版本等)。 程式執行,首先根據manifest清單檔案(這個檔案可以嵌入到exe或dll中,或者單獨生

vs2010生成的exe程式在執行時,提示計算機丟失mfc100d.dll檔案

vs2010開發的exe程式在別的電腦執行時提示,這個問題是因為執行程式的電腦在system32這個資料夾下沒有mfc100ud.dll這個檔案,解決辦法如下: 1、下載一個mfc100ud.dll,然後隨同你的.exe程式一起釋出; 2、需要mfc100ud.dll,說明

嵌入式裝置使用GDB及coredump檔案查詢崩潰問題

背景:1.執行目標為MIPS機器,FLASH及RAM資源都非常緊張,無法執行帶除錯資訊的程式2.程式有一定概率崩潰,從表現上難以分析目標:直接定位到崩潰目的碼說明:1、2在執行環境中操作,3、4在編譯環境中操作1.設定核心轉儲核心轉儲可以儲存程式崩潰時的記憶體狀態。是系統級別

【EXCEL】VS2010;Excel2013;C++控制檯程式;讀檔案

【此處為廢話】這幾天boss讓給他的控制檯程式從TXT讀資料改成從EXCEL讀資料,各種度娘之後發現,真是天下部落格一大抄啊,於是我自己整理了一下。 【未解決】據各種度娘結果,在專案屬性中給已有的控制檯程式新增MFC支援,就可以了,然而,寶寶太渣,如下圖修改後,專案=》類

程式崩潰時生成Dump檔案

Dump檔案是程序的記憶體映象,可以把程式執行時的狀態完整的儲存下來,之後通過除錯工具可查出崩潰大致原因。 SetUnhandledExceptionFilter()設定一個在程式崩潰時被呼叫的回撥函式。MiniDumpWriteDump()建立Dump檔案。 我寫了一個

Android將程式崩潰資訊儲存本地檔案

我們先建立一個crash專案,專案結構如圖: 瞭解以下兩個類:android.app.Application和java.lang.Thread.UncaughtExceptionHandler。 Application:用來管理應用程式的全域性狀態。在應用程

C++程式崩潰時,生成dmp除錯檔案

包含如下標頭檔案 和 引用Lib庫 #include <dbghelp.h> #pragma comment(lib, "dbghelp.lib")定義 LONG WINAPI MyUnh