使用MAP文件快速定位程序崩潰代碼行(轉)

??????作為程序員,平時最擔心見到的事情就是程序發生了崩潰,無論是指針越界還是非法操作,都將給我們的應用系統造成巨大的損失。但在一個大型系統的測試過程中,初期出現程序崩潰似乎成了不可避免的事。其實測試中出現程序崩潰并不可怕,反而是測試的成功。我們更為關心的是程序中的哪一行導致了系統崩潰,這樣我們才能有針對性的進行改正。
  在VC中,我們可以利用出現程序崩潰時VC的自動跳轉,定位到出錯代碼行。但在大量的壓力測試時,尤其是多線程測試時,同時出現幾十個錯,這時VC本身的出錯跳轉往往會失靈。
  在這里我們介紹一種輔助查找程序崩潰代碼行的好方法,它的核心就是利用編譯時生成MAP文件中的信息來定位代碼行。
下面就開始我們的介紹。
  首先我們必須生成程序的MAP文件。那么什么是 MAP 文件呢?簡單地講, MAP 文件是程序的全局符號、源文件和代碼行號信息的唯一的文本表示方法,是整個程序工程信息的靜態文本。它可以在任何地方、任何時候使用,不需要有額外的程序進行支持,僅僅通過一個文本閱讀工具如Ultra Edit就可以打開了。而且,這是唯一能找出程序崩潰代碼行的救星。
  那么我們應該如何生成MAP文件呢?在 VC 中,我們可以按下 Alt+F7,打開“Project Settings”選項頁,選擇 C/C++ 選項卡,并在最下面的 Project Options 里面輸入:/Zd ,然后要選擇 Link 選項卡,選中“Generate mapfile”復選框,并在最下面的 Project Options 里面輸入:/mapinfo:lines,表示生成 MAP 文件時,加入行信息。最后按下 F7 來編譯生成 EXE 可執行文件和 MAP 文件,此時可以在工程的Debug目錄下找到剛剛生成的MAP文件,文件名為“工程名.map”。
  通過上面的步驟,已經得到了 MAP 文件,那么我們該如何利用它呢?讓我們從一個簡單的實例入手,一步一步演示使用MAP文件定位程序崩潰行的過程。
首先假設我們的VC工程中有下面這個文件:
//*****************************************************
// 程序名稱:演示如何通過崩潰地址找出源代碼的出錯行
// 作者:劉可
// 日期:2003-6-19
// 本程序會產生“除0錯誤”,所以會導致
// 程序崩潰,彈出“非法操作”對話框。
//******************************************************
#i nclude

int crashtest(int a,int b)
{
int c;
c = a/b;
return c;
}

void main(void)
{
int a = 30;
int b = 0;
int ret;
printf("let's begin crash test...\n");
ret = crashtest(a,b);
}

很顯然本程序有“除0錯誤”,在 Debug 方式下編譯,運行時會產生“非法操作”。我們記錄下產生崩潰的地址——在我的機器上是 0x0040102f 。這個在不同的機器上可能地址不同,但記下這個地址我們下面將要使用。
我們打開它的 MAP 文件:(這里列出我們比較關心的內容,其他的就略過了)

abort(工程名)

Timestamp is 3ef16533 (Thu Jun 19 15:24:35 2003)

Preferred load address is 00400000

Start    Length    Name        Class
0001:00000000 0001081dH .text        CODE
0002:00000000 000013baH .rdata        DATA
0002:000013ba 00000000H .edata        DATA
0003:00000000 00000104H .CRT$XCA       DATA
0003:00000104 00000104H .CRT$XCZ       DATA
0003:00000208 00000104H .CRT$XIA       DATA
0003:0000030c 00000109H .CRT$XIC       DATA
0003:00000418 00000104H .CRT$XIZ       DATA
0003:0000051c 00000104H .CRT$XPA       DATA
0003:00000620 00000104H .CRT$XPX       DATA
0003:00000724 00000104H .CRT$XPZ       DATA
0003:00000828  00000104H .CRT$XTA       DATA
0003:0000092c  00000104H .CRT$XTZ       DATA
0003:00000a30  00003236H .data        DATA
0003:00003c68  000019c8H .bss        DATA
0004:00000000  00000014H .idata$2       DATA
0004:00000014  00000014H .idata$3       DATA
0004:00000028  00000120H .idata$       DATA
0004:00000148  00000120H .idata$5        DATA
0004:00000268  000004f4H .idata$6       DATA

Address Publics by Value Rva+Base Lib:Object

0001:00000020 ?crashtest@@YAHHH@Z 00401020 f main.obj
0001:0000003c _main 0040103c f main.obj
0001:000000b0 _printf 004010b0 f LIBCD:printf.obj
0001:00000130 __chkesp 00401130 f LIBCD:chkesp.obj
0001:00000170 _mainCRTStartup 00401170 f LIBCD:crt0.obj
0001:000002a0 __amsg_exit 004012a0 f LIBCD:crt0.obj
0001:00000300 __stbuf 00401300 f LIBCD:_sftbuf.obj
0001:00000460 __ftbuf 00401460 f LIBCD:_sftbuf.obj
0001:00000520 __output 00401520 f LIBCD:output.obj
0001:000013c0 ___initstdio 004023c0 f LIBCD:_file.obj
0001:000014f0 ___endstdio 004024f0 f LIBCD:_file.obj
0001:00001510 __CrtDbgBreak 00402510 f LIBCD:dbgrpt.obj
0001:00001520 __CrtSetReportMode 00402520 f LIBCD:dbgrpt.obj
0001:00001580 __CrtSetReportFile 00402580 f LIBCD:dbgrpt.obj
0001:00001600 __CrtSetReportHook 00402600 f LIBCD:dbgrpt.obj
0001:00001620 __CrtDbgReport 00402620 f LIBCD:dbgrpt.obj

  如果仔細瀏覽 Rva+Base 這欄,我們可以發現第一個比崩潰地址 0x0040102f 大的函數地址是 0x0040103c ,所以在 0x0040103c 這個地址之前的那個入口就是產生崩潰的函數,也就是這行:

0001:00000020 ?crashtest@@YAHHH@Z 00401020 f main.obj

  因此,發生崩潰的函數就是 ?crashtest@@YAHHH@Z,所有以問號開頭的函數名稱都是 C++ 修飾的名稱。所以在我們的源程序中,這個發生崩潰的函數就是 crashtest ()!

  現在我們便輕而易舉地知道了發生崩潰的函數名稱。把它記下來,然后我們將要直接定位發生崩潰的代碼行了。我們注意 MAP 文件的最后部分——代碼行信息(Line numbers information),它是以這樣的形式顯示的:

Line numbers for .\Debug\main.obj(D:\我的工作\技術\出異常例子abort\main.cpp) segment .text

12 0001:00000020 14 0001:0000002b 15 0001:00000035 16 0001:00000038
19 0001:0000003c 20 0001:00000057 21 0001:0000005e 23 0001:00000065
24 0001:00000072 25 0001:00000085

  第一個數字代表在源代碼中的代碼行號,第二個數是該代碼行在所屬的代碼段中的偏移量。如果要查找代碼行號,需要使用下面的公式做一些十六進制的減法運算:

崩潰行偏移 = 崩潰地址(Crash Address)- 基地址(ImageBase Address)- 0x1000

  為什么要這樣做呢?因為我們得到的崩潰地址都是由 偏移地址(Rva)+ 基地址(Base)得來的,所以在計算行號的時候要把基地址減去。一般情況下,基地址的值是 0x00400000 。另外,由于一般的 PE 文件的代碼段都是從 0x1000 偏移開始的,所以也必須減去 0x1000 。
  所以我們的:崩潰行偏移 = 0x0040102f - 0x00400000 - 0x1000 = 0x2f
我們在MAP 文件的中的代碼行信息里查找不超過計算結果0x2f,但卻最接近的數。發現是 main.cpp 文件中的:

14 0001:0000002b

  也就意味著在源代碼中的第 14 行!讓我們來看看源代碼,注意注釋行和空行也要計算在內,程序的第14行為:

c = a/b;

果然就是第 14 行啊,它發生了“除0異常”!

  方法已經介紹完了,從今以后,我們就可以精確地定位到源代碼中的崩潰行,而且只要編譯器可以生成 MAP 文件,無論在WIN平臺還是UNIX平臺,本方法都是適用的。
  本文我們只是列舉了一個非常簡單的“除0異常”例子,使用MAP文件的效力或許還不十分明顯。但相信在我們的大型應用系統調試中,使用MAP文件的輔助方法來快速定位發生程序崩潰的函數以及代碼行,將會為我們的程序調試工作節省大量時間和精力,提高我們的調試質量。我們甚至可以要求遠地用戶直接提供程序崩潰的地址,然后就可以在自己機器上利用MAP文件靜態地找到出錯的那行,并在程序中進行相應修正了。

?

轉載于:https://www.cnblogs.com/Phoenix-Rock/archive/2009/08/13/1545375.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276422.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276422.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276422.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

構建安全的Xml Web Service系列之如何察看SoapMessage

上一篇文章地址:構建安全的Xml Web Service系列一之初探使用Soap頭 (5-22 12:53) 要分析Xml Web Service的安全性,首先要解決的問題是我們能了解和清楚Soap消息的格式和內容,如果獲得不了SoapMessage,分析如何能構建安全Xml w…

前端高效開發必備的 js 庫梳理

之前有很多人問學好前端需要學習哪些 js 庫, 主流框架應該學 vue 還是 react ? 針對這些問題, 筆者來說說自己的看法和學習總結.首先我覺得在學習任何知識之前必須要有一個明確的學習目標, 知道自己為什么要學它, 而不是看網上說的一股腦的給你灌輸各種知識, 讓你學習各種庫, …

交叉報表crosstab隱藏列名顯示_SAP軟件 報表查詢之 輸出格式設置

SAP不僅是功能強大、邏輯嚴謹的ERP軟件,還提供了強大的報表查詢功能。SAP的ALV報表展示功能是SAP的一大特點,實現了類似于EXCEL的功能。使用好ALV報表功能可以方便用戶從SAP中取到想要的數據,尤其是財務用戶。大家在使用SAP報表時&#xff0c…

CSS HACK 區別 IE6、IE7、IE8、Firefox兼容性

轉載鏈接:http://developer.51cto.com/art/201009/226787_1.htm 本文向大家描述一下如何使用CSS HACK區別IE6、IE7、IE8、Firefox兼容性問題,針對不同的瀏覽器寫不同的CSS code的過程,就叫CSS hack,也叫寫CSS hack,相信你對本文介…

Flex sdk4 布局與更新

在flex中,主要使用LayoutManager來驅動組件的度量和布局策略, LayoutManager實現一個單例,在Application類構造函數中創建: 1 public functionApplication()2 {3 UIComponentGlobals.layoutManager ILayoutManager(4 Singleton.getInstance("mx.managers::ILayoutManager&…

linux PROC文件系統詳解

/proc文件系統下的多種文件提供的系統信息不是針對某個特定進程的,而是能夠在整個系統范圍的上下文中使用。可以使用的文件隨系統配置的變化而變化。命令procinfo能夠顯示基于其中某些文件的多種系統信息。以下詳細描述/proc下的文件。----------------------------…

seo每日一貼_白楊SEO:我看ZAC的外貿SEO應該怎樣做?(策略篇)

前言:這是白楊SEO公眾號更新第64篇。本該寫寫頭條SEO啥的,最近在師徒培訓講站內SEO時有旁聽同學提到后面講講谷歌SEO怎么樣,因為谷歌全世界搜索市場占有率,所以外貿SEO最主要還是做谷歌SEO。以白楊特意又去了前輩ZAC的SEO每日一貼…

Can't connect to local MySQL server through socket '/tmp/mysql.sock'

轉載鏈接:http://blog.csdn.net/ixidof/article/details/5958904 摘要:解決不能通過mysql .sock連接MySQL問題 這個問題主要提示是,不能通過 /tmp/mysql .sock連到服務器,而php標準配置正是用過/tmp/mysql .sock,但是…

[轉]網頁柵格系統研究(2):蛋糕的切法

[出自]http://lifesinger.org/blog/2008/10/grid-system-2/首先澄清一個應用場景問題。研究(1)中指出,對于結構復雜的網站,不少設計師們喜歡采用960固定寬度布局。但要注意的是,960并不是萬能鑰匙,大部分網…

Vue3響應式原理

關注若川視野,回復"pdf" 領取資料,回復"加群",可加群長期交流學習本文結構- 關于Vue3- Vue2響應式原理回顧- Vue3響應式方案- Vue3響應式原理- 手寫mini版Vue3響應式本文共計:2349字2圖預計閱讀時間&#xff…

python二值化 感興趣區域_Python+OpenCV感興趣區域ROI提取方法

方法一:使用輪廓步驟1"""src為原圖"""ROI np.zeros(src.shape, np.uint8) #感興趣區域ROIproimage src.copy() #復制原圖"""提取輪廓"""proimagecv2.cvtColor(proimage,cv2.COLOR_BGR2GRAY) #轉換成…

error while loading shared libraries: libmysqlclient.so.16: cannot open

轉載鏈接:http://blog.sina.com.cn/s/blog_4ab24dd50100wnkv.html 問題解決辦法: locate libmysqlclient.so.16 如我的mysql安裝在/usr/local/mysql下,則結果為 /usr/local/mysql/lib/mysql/libmysqlclient.so.16 vi /etc/ld.so.conf 增…

編譯cvaux錯誤的原因

平臺vc6.0;在debug模式下編譯cvaux時會提示三個錯誤:error C2039: foreground_regions : is not a member of CvFGDStatModelerror C2039: foreground_regions : is not a member of CvFGDStatModelerror C2039: foreground_regions : is not a member of CvGaussBG…

找準切入點,調試看源碼,事半功倍

關注若川視野,回復"pdf" 領取資料,回復"加群",可加群長期交流學習最近寫了很多源碼分析相關的文章,React、Vue 都有,想把我閱讀源碼的一些心得分享給大家。React:React 架構的演變 - 從…

Android布局大全

Android的界面是有布局和組件協同完成的,布局好比是建筑里的框架,而組件則相當于建筑里的磚瓦。組件按照布局的要求依次排列,就組成了用戶所看見的界面。 所有的布局方式都可以歸類為ViewGroup的5個類別,即ViewGroup的5個直接子類…

java實現加減乘除運算符隨機生成十道題并判斷對錯_2020年Java面試題(3年的工作總結),最全的知識點總結...

這份Java面試題整整花了三個月的時間來整理,都是自己再工作中總結出來,記住多少就寫多少,希望這份資料可以幫助你們,文末有其余部分資料的領取方式.Redis12道面試題1.什么是Redis?答:Remote Dictionary Ser…

Linux MySQL 5.1.62 source install

源碼包官網下載:http://dev.mysql.com/downloads/ MySQL手冊官網下載:http://dev.mysql.com/doc/ 安裝ncurses: 1、tar -zxvf ncurses-5.9.tar.gz 2、cd ncurses-5.9.tar.gz ; ./configure; make clean; make; make install 修改時區…

RDLC 示例 文章 1

GotReportViewer的實例,請在下面的連接中下載: http://files.cnblogs.com/waxdoll/RDLC.rar http://www.databasejournal.com/features/mssql/article.php/3605826/Mastering-OLAP-Reporting--Reporting-with-Analysis-Services-KPIs.htm MSSQL Server …

.NET 中的泛型 101

1.1.1 摘要 圖1 C# 泛型介紹 在接觸泛型之前,我們編程一般都是使用具體類型(char, int, string等)或自定義類型來定義我們變量,如果我們有一個功能很強的接口,而且我們想把它提取或重構成一個通用的接口,使…

年底了,給想進階的的前端朋友一些福利

2020 年,很多朋友都經歷了一段比較艱難的求職季。年末,“就業寒冬”迎來了一絲暖陽,很多中大型互聯網公司擴大了未來一年的招聘需求。前不久,字節跳動放出了年末要招 1 萬人的消息,騰訊校招規模也將擴張至 5000 人&…