青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

拂曉·明月·彎刀

觀望,等待只能讓出現(xiàn)的機會白白溜走

  C++博客 :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
最近看了周星星 Blog 中的一篇文章:“VC++6.0中內存泄漏檢測”,受益匪淺,便運行其例子代碼想看看 Output 窗口中的輸出結果,可惜怎么弄其輸出都不是預期的東西,郁悶了半天,便到水壇里找到周星星,請求他指點一、二,然而未果。沒有辦法,最后我一頭栽進 MSDN 庫狂搜了一把,功夫不負有心人,我搜出很多有關這方面的資料,沒過多久我便基本上就找到了答案......
首先,檢測內存泄漏的基本工具是調試器和 CRT 調試堆函數(shù)。為了使用調試堆函數(shù),必須在要檢測內存泄漏和調試的程序中添加下面的語句:
#define _CRTDBG_MAP_ALLOC  #include<stdlib.h>  #include<crtdbg.h>   #include "debug_new.h" 

  MSDN 如是說:“必須保證上面聲明的順序,如果改變了順序,可能不能正常工作。”至于這是為什么,我們不得而知。MS 的老大們經(jīng)常這樣故弄玄虛。
針對非 MFC 程序,再加上周星星的頭文件:debug_new.h,當然如果不加這一句,也能檢測出內存泄漏,但是你無法確定在哪個源程序文件中發(fā)生泄漏。Output 輸出只告訴你在 crtsdb.h 中的某個地方有內存泄漏。我測試時 REG_DEBUG_NEW 沒有起作用。加不加這個宏都可以檢測出發(fā)生內存分配泄漏的文件。
其次,一旦添加了上面的聲明,你就可以通過在程序中加入下面的代碼來報告內存泄漏信息了:

      _CrtDumpMemoryLeaks(); 
  這就這么簡單。我在周星星的例子代碼中加入這些機關后,在 VC++ 調試會話(按 F5 調試運行) Output 窗口的 Debug 頁便看到了預期的內存泄漏 dump。該 dump 形式如下:
Detected memory leaks!  Dumping objects ->  c:\Program Files\...\include\crtdbg.h(552) : {45} normal block at 0x00441BA0, 2 bytes long.  Data: <AB> 41 42  c:\Program Files\...\include\crtdbg.h(552) : {44} normal block at 0x00441BD0, 33 bytes long.  Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD  c:\Program Files\...\include\crtdbg.h(552) : {43} normal block at 0x00441C20, 40 bytes long.  Data: < C > E8 01 43 00 16 00 00 00 00 00 00 00 00 00 00 00  Object dump complete. 

更具體的細節(jié)請參考本文附帶的源代碼文件。

下面是我看過 MSDN 資料后,針對“如何使用 CRT 調試功能來檢測內存泄漏?”的問題進行了一番編譯和整理,希望對大家有用。如果你的英文很棒,那就不用往下看了,建議直接去讀 MSDN 庫中的技術原文。
C/C++ 編程語言的最強大功能之一便是其動態(tài)分配和釋放內存,但是中國有句古話:“最大的長處也可能成為最大的弱點”,那么 C/C++ 應用程序正好印證了這句話。在 C/C++ 應用程序開發(fā)過程中,動態(tài)分配的內存處理不當是最常見的問題。其中,最難捉摸也最難檢測的錯誤之一就是內存泄漏,即未能正確釋放以前分配的內存的錯誤。偶爾發(fā)生的少量內存泄漏可能不會引起我們的注意,但泄漏大量內存的程序或泄漏日益增多的程序可能會表現(xiàn)出各種 各樣的征兆:從性能不良(并且逐漸降低)到內存完全耗盡。更糟的是,泄漏的程序可能會用掉太多內存,導致另外一個程序垮掉,而使用戶無從查找問題的真正根源。此外,即使無害的內存泄漏也可能殃及池魚。
幸運的是,Visual Studio 調試器和 C 運行時 (CRT) 庫為我們提供了檢測和識別內存泄漏的有效方法。下面請和我一起分享收獲——如何使用 CRT 調試功能來檢測內存泄漏?

  1. 如何啟用內存泄漏檢測機制?
  2. 解釋內存塊類型
  3. 如何在內存分配序號處設置斷點?
  4. 如何比較內存狀態(tài)?
  5. 結論

如何啟用內存泄漏檢測機制

  VC++ IDE 的默認狀態(tài)是沒有啟用內存泄漏檢測機制的,也就是說即使某段代碼有內存泄漏,調試會話的 Output 窗口的 Debug 頁不會輸出有關內存泄漏信息。你必須設定兩個最基本的機關來啟用內存泄漏檢測機制。

一是使用調試堆函數(shù):

#define _CRTDBG_MAP_ALLOC  #include<stdlib.h>  #include<crtdbg.h> 

注意:#include 語句的順序。如果更改此順序,所使用的函數(shù)可能無法正確工作。

通過包含 crtdbg.h 頭文件,可以將 malloc 和 free 函數(shù)映射到其“調試”版本 _malloc_dbg 和 _free_dbg,這些函數(shù)會跟蹤內存分配和釋放。此映射只在調試(Debug)版本(也就是要定義 _DEBUG)中有效。發(fā)行版本(Release)使用普通的 malloc 和 free 函數(shù)。
#define 語句將 CRT 堆函數(shù)的基礎版本映射到對應的“調試”版本。該語句不是必須的,但如果沒有該語句,那么有關內存泄漏的信息會不全。

二是在需要檢測內存泄漏的地方添加下面這條語句來輸出內存泄漏信息:

_CrtDumpMemoryLeaks();
  當在調試器下運行程序時,_CrtDumpMemoryLeaks 將在 Output 窗口的 Debug 頁中顯示內存泄漏信息。比如:
Detected memory leaks! Dumping objects -> C:\Temp\memleak\memleak.cpp(15) : {45} normal block at 0x00441BA0, 2 bytes long. Data: <AB> 41 42  c:\program files\microsoft visual studio\vc98\include\crtdbg.h(552) : {44} normal block at 0x00441BD0, 33 bytes long. Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD  c:\program files\microsoft visual studio\vc98\include\crtdbg.h(552) : {43} normal block at 0x00441C20, 40 bytes long. Data: < C > 08 02 43 00 16 00 00 00 00 00 00 00 00 00 00 00  Object dump complete.

如果不使用 #define _CRTDBG_MAP_ALLOC 語句,內存泄漏的輸出是這樣的:

Detected memory leaks! Dumping objects -> {45} normal block at 0x00441BA0, 2 bytes long. Data: <AB> 41 42  {44} normal block at 0x00441BD0, 33 bytes long. Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD  {43} normal block at 0x00441C20, 40 bytes long. Data: < C > C0 01 43 00 16 00 00 00 00 00 00 00 00 00 00 00  Object dump complete.
  根據(jù)這段輸出信息,你無法知道在哪個源程序文件里發(fā)生了內存泄漏。下面我們來研究一下輸出信息的格式。第一行和第二行沒有什么可說的,從第三行開始:
xx}:花括弧內的數(shù)字是內存分配序號,本文例子中是 {45},{44},{43}; block:內存塊的類型,常用的有三種:normal(普通)、client(客戶端)或 CRT(運行時);本文例子中是:normal block;  用十六進制格式表示的內存位置,如:at 0x00441BA0 等; 以字節(jié)為單位表示的內存塊的大小,如:32 bytes long;  前 16 字節(jié)的內容(也是用十六進制格式表示),如:Data: <AB> 41 42 等;

  仔細觀察不難發(fā)現(xiàn),如果定義了 _CRTDBG_MAP_ALLOC ,那么在內存分配序號前面還會顯示在其中分配泄漏內存的文件名,以及文件名后括號中的數(shù)字表示發(fā)生泄漏的代碼行號,比如:

C:\Temp\memleak\memleak.cpp(15) 
  雙擊 Output 窗口中此文件名所在的輸出行,便可跳到源程序文件分配該內存的代碼行(也可以選中該行,然后按 F4,效果一樣) ,這樣一來我們就很容易定位內存泄漏是在哪里發(fā)生的了,因此,_CRTDBG_MAP_ALLOC 的作用顯而易見。

使用 _CrtSetDbgFlag

如果程序只有一個出口,那么調用 _CrtDumpMemoryLeaks 的位置是很容易選擇的。但是,如果程序可能會在多個地方退出該怎么辦呢?在每一個可能的出口處調用 _CrtDumpMemoryLeaks 肯定是不可取的,那么這時可以在程序開始處包含下面的調用:
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

  這條語句無論程序在什么地方退出都會自動調用 _CrtDumpMemoryLeaks。注意:這里必須同時設置兩個位域標志:_CRTDBG_ALLOC_MEM_DF 和 _CRTDBG_LEAK_CHECK_DF。

設置 CRT 報告模式

默認情況下,_CrtDumpMemoryLeaks 將內存泄漏信息 dump 到 Output 窗口的 Debug 頁, 如果你想將這個輸出定向到別的地方,可以使用 _CrtSetReportMode 進行重置。如果你使用某個庫,它可能將輸出定向到另一位置。此時,只要使用以下語句將輸出位置設回 Output 窗口即可:

_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );

有關使用 _CrtSetReportMode 的詳細信息,請參考 MSDN 庫關于 _CrtSetReportMode 的描述。

解釋內存塊類型

前面已經(jīng)說過,內存泄漏報告中把每一塊泄漏的內存分為 normal(普通塊)、client(客戶端塊)和 CRT 塊。事實上,需要留心和注意的也就是 normal 和 client,即普通塊和客戶端塊。

  • normal block(普通塊):這是由你的程序分配的內存。
  • client block(客戶塊):這是一種特殊類型的內存塊,專門用于 MFC 程序中需要析構函數(shù)的對象。MFC new 操作符視具體情況既可以為所創(chuàng)建的對象建立普通塊,也可以為之建立客戶塊。
  • CRT block(CRT 塊):是由 C RunTime Library 供自己使用而分配的內存塊。由 CRT 庫自己來管理這些內存的分配與釋放,我們一般不會在內存泄漏報告中發(fā)現(xiàn) CRT 內存泄漏,除非程序發(fā)生了嚴重的錯誤(例如 CRT 庫崩潰)。

除了上述的類型外,還有下面這兩種類型的內存塊,它們不會出現(xiàn)在內存泄漏報告中:

  • free block(空閑塊):已經(jīng)被釋放(free)的內存塊。
  • Ignore block(忽略塊):這是程序員顯式聲明過不要在內存泄漏報告中出現(xiàn)的內存塊。

如何在內存分配序號處設置斷點?

  在內存泄漏報告中,的文件名和行號可告訴分配泄漏的內存的代碼位置,但僅僅依賴這些信息來了解完整的泄漏原因是不夠的。因為一個程序在運行時,一段分配內存的代碼可能會被調用很多次,只要有一次調用后沒有釋放內存就會導致內存泄漏。為了確定是哪些內存沒有被釋放,不僅要知道泄漏的內存是在哪里分配的,還要知道泄漏產(chǎn)生的條件。這時內存分配序號就顯得特別有用——這個序號就是文件名和行號之后的花括弧里的那個數(shù)字。
例如,在本文例子代碼的輸出信息中,“45”是內存分配序號,意思是泄漏的內存是你程序中分配的第四十五個內存塊:

Detected memory leaks! Dumping objects -> C:\Temp\memleak\memleak.cpp(15) : {45} normal block at 0x00441BA0, 2 bytes long. Data: <AB> 41 42  ...... Object dump complete. 

  CRT 庫對程序運行期間分配的所有內存塊進行計數(shù),包括由 CRT 庫自己分配的內存和其它庫(如 MFC)分配的內存。因此,分配序號為 N 的對象即為程序中分配的第 N 個對象,但不一定是代碼分配的第 N 個對象。(大多數(shù)情況下并非如此。)
這樣的話,你便可以利用分配序號在分配內存的位置設置一個斷點。方法是在程序起始附近設置一個位置斷點。當程序在該點中斷時,可以從 QuickWatch(快速監(jiān)視)對話框或 Watch(監(jiān)視)窗口設置一個內存分配斷點:

例如,在 Watch 窗口中,在 Name 欄鍵入下面的表達式:

_crtBreakAlloc

如果要使用 CRT 庫的多線程 DLL 版本(/MD 選項),那么必須包含上下文操作符,像這樣:

{,,msvcrtd.dll}_crtBreakAlloc

  現(xiàn)在按下回車鍵,調試器將計算該值并把結果放入 Value 欄。如果沒有在內存分配點設置任何斷點,該值將為 –1。
用你想要在其位置中斷的內存分配的分配序號替換 Value 欄中的值。例如輸入 45。這樣就會在分配序號為 45 的地方中斷。 
在所感興趣的內存分配處設置斷點后,可以繼續(xù)調試。這時,運行程序時一定要小心,要保證內存塊分配的順序不會改變。當程序在指定的內存分配處中斷時,可以查看 Call Stack(調用堆棧)窗口和其它調試器信息以確定分配內存時的情況。如果必要,可以從該點繼續(xù)執(zhí)行程序,以查看對象發(fā)生了什么情況,或許可以確定未正確釋放對象的原因。
盡管通常在調試器中設置內存分配斷點更方便,但如果愿意,也可在代碼中設置這些斷點。為了在代碼中設置一個內存分配斷點,可以增加這樣一行(對于第四十五個內存分配):

_crtBreakAlloc = 45;

你還可以使用有相同效果的 _CrtSetBreakAlloc 函數(shù):

_CrtSetBreakAlloc(45);

如何比較內存狀態(tài)?

  定位內存泄漏的另一個方法就是在關鍵點獲取應用程序內存狀態(tài)的快照。CRT 庫提供了一個結構類型 _CrtMemState。你可以用它來存儲內存狀態(tài)的快照:

_CrtMemState s1, s2, s3;

  若要獲取給定點的內存狀態(tài)快照,可以向 _CrtMemCheckpoint 函數(shù)傳遞一個 _CrtMemState 結構。該函數(shù)用當前內存狀態(tài)的快照填充此結構:

_CrtMemCheckpoint( &s1 );

  通過向 _CrtMemDumpStatistics 函數(shù)傳遞 _CrtMemState 結構,可以在任意地方 dump 該結構的內容:

_CrtMemDumpStatistics( &s1 );

該函數(shù)輸出如下格式的 dump 內存分配信息:

0 bytes in 0 Free Blocks. 75 bytes in 3 Normal Blocks. 5037 bytes in 41 CRT Blocks. 0 bytes in 0 Ignore Blocks. 0 bytes in 0 Client Blocks. Largest number used: 5308 bytes. Total allocations: 7559 bytes.

  若要確定某段代碼中是否發(fā)生了內存泄漏,可以通過獲取該段代碼之前和之后的內存狀態(tài)快照,然后使用 _CrtMemDifference 比較這兩個狀態(tài):

_CrtMemCheckpoint( &s1 );// 獲取第一個內存狀態(tài)快照  // 在這里進行內存分配  _CrtMemCheckpoint( &s2 );// 獲取第二個內存狀態(tài)快照  // 比較兩個內存快照的差異 if ( _CrtMemDifference( &s3, &s1, &s2) )      _CrtMemDumpStatistics( &s3 );// dump 差異結果

  顧名思義,_CrtMemDifference 比較兩個內存狀態(tài)(前兩個參數(shù)),生成這兩個狀態(tài)之間差異的結果(第三個參數(shù))。在程序的開始和結尾放置 _CrtMemCheckpoint 調用,并使用 _CrtMemDifference 比較結果,是檢查內存泄漏的另一種方法。如果檢測到泄漏,則可以使用 _CrtMemCheckpoint 調用通過二進制搜索技術來分割程序和定位泄漏。

結論

盡管 VC ++ 具有一套專門調試 MFC 應用程序的機制,但本文上述討論的內存分配很簡單,沒有涉及到 MFC 對象,所以這些內容同樣也適用于 MFC 程序。在 MSDN 庫中可以找到很多有關 VC++ 調試方面的資料,如果你能善用 MSDN 庫,相信用不了多少時間你就有可能成為調試高手。

本人水平不高,謬誤在所難免,請大家拍磚,不要客氣。順祝大家圣誕快樂!

JerryZ 于 2004 年平安夜,

 

調試方法和技巧

作者:
非凡

便于調試的代碼風格:

  1. 不用全局變量
  2. 所有變量都要初始化,成員變量在構造函數(shù)中初始化
  3. 盡量使用const
  4. 詳盡的注釋

VC++編譯選項:

  1. 總是使用/W4警告級別
  2. 在調試版本里總是使用/GZ編譯選項,用來發(fā)現(xiàn)在Release版本中才有的錯誤
  3. 沒有警告的編譯:保證在編譯后沒有任何警告,但是在消除警告前要進行仔細檢查

調試方法:

1、使用 Assert(原則:盡量簡單)
assert只在debug下生效,release下不會被編譯。

例子:

char* strcpy(char* dest,char* source) { 	assert(source!=0); 	assert(dest!=0); 	char* returnstring = dest; 	 	while((*dest++ = *source++)!= ‘\0’) 	{ 		; 	} 	return returnstring; }      

2、防御性的編程

例子:

char* strcpy(char* dest,char* source) { 	if(source == 0) 	{ 		assert(false); 		reutrn 0; 	}  	if(dest == 0) 	{ 		assert(false); 		return 0; 	} 	char* returnstring = dest; 	while((*dest++ = *source++)!= ‘\0’) 	{ 		; 	} 	return returnstring; }      

3、使用Trace

以下的例子只能在debug中顯示,

例子:

a)、TRACE

CString csTest = “test”; TRACE(“CString is %s\n”,csTest);

b)、ATLTRACE

c)、afxDump

CTime time = CTime::GetCurrentTime(); #ifdef _DEBUG afxDump << time << “\n”; #endif

4、用GetLastError來檢測返回值,通過得到錯誤代碼來分析錯誤原因

5、把錯誤信息記錄到文件中

異常處理

程序設計時一定要考慮到異常如何處理,當錯誤發(fā)生后,不應簡單的報告錯誤并退出程序,應當盡可能的想辦法恢復到出錯前的狀態(tài)或者讓程序從頭開始運行,并且對于某些錯誤,應該能夠容錯,即允許錯誤的存在,但是程序還是能夠正常完成任務。

調試技巧

1、VC++中F5進行調試運行

a)、在output Debug窗口中可以看到用TRACE打印的信息
b)、 Call Stack窗口中能看到程序的調用堆棧

2、當Debug版本運行時發(fā)生崩潰,選擇retry進行調試,通過看Call Stack分析出錯的位置及原因
3、使用映射文件調試

a)、創(chuàng)建映射文件:Project settings中l(wèi)ink項,選中Generate mapfile,輸出程序代碼地址:/MAPINFO: LINES,得到引出序號:/MAPINFO: EXPORTS。
b)、程序發(fā)布時,應該把所有模塊的映射文件都存檔。
c)、查看映射文件:見” 通過崩潰地址找出源代碼的出錯行”文件。

4、可以調試的Release版本

Project settings中C++項的Debug Info選擇為Program Database,Link項的Debug中選擇Debug Info和Microsoft format。

5、查看API的錯誤碼,在watch窗口輸入@err可以查看或者@err,hr,其中”,hr”表示錯誤碼的說明。
6、Set Next Statement:該功能可以直接跳轉到指定的代碼行執(zhí)行,一般用來測試異常處理的代碼。
7、調試內存變量的變化:當內存發(fā)生變化時停下來。

常見錯誤

1、在函數(shù)返回的時候程序崩潰的原因

a)、寫自動變量越界
b)、函數(shù)原型不匹配

2、MFC

a)、使用錯誤的函數(shù)原型處理用戶定義消息

正確的函數(shù)原型為:

afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);

3、謹慎使用TerminateThread:使用TerminateThread會造成資源泄漏,不到萬不得已,不要使用。

4、使用_beginthreadex,不要使用Create Thread來常見線程。

參考資料:
《Windows程序調試》

功能強大的vc6調試器


作者:
yy2better


  要成為一位優(yōu)秀的軟件工程師,調試能力必不可缺。本文將較詳細介紹VC6調試器的主要用法。 
  windows平臺的調試器主要分為兩大類: 
  1 用戶模式(user-mode)調試器:它們都基于win32 Debugging API,有使用方便的界面,主要用于調試用戶模式下的應用程序。這類調試器包括Visual C++調試器、WinDBG、BoundChecker、Borland C++ Builder調試器、NTSD等。 
  2 內核模式(kernel-mode)調試器:內核調試器位于CPU和操作系統(tǒng)之間,一旦啟動,操作系統(tǒng)也會中止運行,主要用于調試驅動程序或用戶模式調試器不易調試的程序。這類調試器包括WDEB386、WinDBG和softice等。其中WinDBG和softice也可以調試用戶模式代碼。 
  國外一位調試高手曾說,他70%調試時間是在用VC++,其余時間是使用WinDBG和softice。畢竟,調試用戶模式代碼,VC6調試器的效率是非常高的。因此,我將首先在本篇介紹VC6調試器的主要用法,其他調試器的用法及一些調試技能在后續(xù)文章中闡述。 

一 位置斷點(Location Breakpoint) 
  大家最常用的斷點是普通的位置斷點,在源程序的某一行按F9就設置了一個位置斷點。但對于很多問題,這種樸素的斷點作用有限。譬如下面這段代碼:

void CForDebugDlg::OnOK() 	 { 	for (int i = 0; i < 1000; i++)	//A 	{ 		int k = i * 10 - 2;	//B 		SendTo(k);		//C 		int tmp = DoSome(i);	//D 		int j = i / tmp;	//E 	} }             

  執(zhí)行此函數(shù),程序崩潰于E行,發(fā)現(xiàn)此時tmp為0,假設tmp本不應該為0,怎么這個時候為0呢?所以最好能夠跟蹤此次循環(huán)時DoSome函數(shù)是如何運行的,但由于是在循環(huán)體內,如果在E行設置斷點,可能需要按F5(GO)許多次。這樣手要不停的按,很痛苦。使用VC6斷點修飾條件就可以輕易解決此問題。步驟如下。 
  1 Ctrl+B打開斷點設置框,如下圖: 
 
Figure 1設置高級位置斷點 
  2 然后選擇D行所在的斷點,然后點擊condition按鈕,在彈出對話框的最下面一個編輯框中輸入一個很大數(shù)目,具體視應用而定,這里1000就夠了。 
  3 按F5重新運行程序,程序中斷。Ctrl+B打開斷點框,發(fā)現(xiàn)此斷點后跟隨一串說明:...487 times remaining。意思是還剩下487次沒有執(zhí)行,那就是說執(zhí)行到513(1000-487)次時候出錯的。因此,我們按步驟2所講,更改此斷點的skip次數(shù),將1000改為513。 
  4 再次重新運行程序,程序執(zhí)行了513次循環(huán),然后自動停在斷點處。這時,我們就可以仔細查看DoSome是如何返回0的。這樣,你就避免了手指的痛苦,節(jié)省了時間。 
  再看位置斷點其他修飾條件。如Figure 1所示,在“Enter the expression to be evaluated:”下面,可以輸入一些條件,當這些條件滿足時,斷點才啟動。譬如,剛才的程序,我們需要i為100時程序停下來,我們就可以輸入在編輯框中輸入“i==100”。 
  另外,如果在此編輯框中如果只輸入變量名稱,則變量發(fā)生改變時,斷點才會啟動。這對檢測一個變量何時被修改很方便,特別對一些大程序。 
  用好位置斷點的修飾條件,可以大大方便解決某些問題。 

二 數(shù)據(jù)斷點(Data Breakpoint) 
  軟件調試過程中,有時會發(fā)現(xiàn)一些數(shù)據(jù)會莫名其妙的被修改掉(如一些數(shù)組的越界寫導致覆蓋了另外的變量),找出何處代碼導致這塊內存被更改是一件棘手的事情(如果沒有調試器的幫助)。恰當運用數(shù)據(jù)斷點可以快速幫你定位何時何處這個數(shù)據(jù)被修改。譬如下面一段程序:

#include "stdafx.h" #include   int main(int argc, char* argv[]) { 	char szName1[10]; 	char szName2[4]; 	strcpy(szName1,"shenzhen");		 	printf("%s\n", szName1);		//A  	strcpy(szName2, "vckbase");		//B 	printf("%s\n", szName1); 	printf("%s\n", szName2);  	return 0; }       

  這段程序的輸出是

      	szName1: shenzhen 	szName1: ase 	szName2: vckbase      

szName1何時被修改呢?因為沒有明顯的修改szName1代碼。我們可以首先在A行設置普通斷點,F(xiàn)5運行程序,程序停在A行。然后我們再設置一個數(shù)據(jù)斷點。如下圖: 
 
Figure 2 數(shù)據(jù)斷點 
  F5繼續(xù)運行,程序停在B行,說明B處代碼修改了szName1。B處明明沒有修改szName1呀?但調試器指明是這一行,一般不會錯,所以還是靜下心來看看程序,哦,你發(fā)現(xiàn)了:szName2只有4個字節(jié),而strcpy了7個字節(jié),所以覆寫了szName1。 
  數(shù)據(jù)斷點不只是對變量改變有效,還可以設置變量是否等于某個值。譬如,你可以將Figure 2中紅圈處改為條件”szName2[0]==''''y''''“,那么當szName2第一個字符為y時斷點就會啟動。 
  可以看出,數(shù)據(jù)斷點相對位置斷點一個很大的區(qū)別是不用明確指明在哪一行代碼設置斷點。 

三 其他 
  1 在call stack窗口中設置斷點,選擇某個函數(shù),按F9設置一個斷點。這樣可以從深層次的函數(shù)調用中迅速返回到需要的函數(shù)。 
  2 Set Next StateMent命令(debug過程中,右鍵菜單中的命令) 
  此命令的作用是將程序的指令指針(EIP)指向不同的代碼行。譬如,你正在調試上面那段代碼,運行在A行,但你不愿意運行B行和C行代碼,這時,你就可以在D行,右鍵,然后“Set Next StateMent”。調試器就不會執(zhí)行B、C行。只要在同一函數(shù)內,此指令就可以隨意跳前或跳后執(zhí)行。靈活使用此功能可以大量節(jié)省調試時間。 
  3 watch窗口 
  watch窗口支持豐富的數(shù)據(jù)格式化功能。如輸入0x65,u,則在右欄顯示101。 
  實時顯示windows API調用的錯誤:在左欄輸入@err,hr。 
  在watch窗口中調用函數(shù)。提醒一下,調用完函數(shù)后馬上在watch窗口中清除它,否則,單步調試時每一步調試器都會調用此函數(shù)。 
  4 messages斷點不怎么實用。基本上可以用前面講述的斷點代替。 
總結 
  調試最重要的還是你要思考,要猜測你的程序可能出錯的地方,然后運用你的調試器來證實你的猜測。而熟練使用上面這些技巧無疑會加快這個過程。最后,大家如果有關于調試方面的問題,我樂意參與探討。


posted on 2011-03-23 00:00 一路風塵 閱讀(704) 評論(0)  編輯 收藏 引用 所屬分類: 轉載
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产亚洲精品久久久久动| 欧美黑人国产人伦爽爽爽| 久久免费视频观看| 亚洲人成网站色ww在线| 美女成人午夜| 欧美一级黄色网| 欧美一级艳片视频免费观看| 一本色道久久88综合亚洲精品ⅰ | 亚洲无线一线二线三线区别av| 久热国产精品| 在线性视频日韩欧美| 欧美自拍偷拍| 欧美日韩精品综合在线| 亚洲午夜av在线| 亚洲免费在线播放| 日韩亚洲一区二区| 亚洲国产日韩一级| 久久午夜精品| 欧美午夜电影一区| 你懂的国产精品永久在线| 国产精品视频导航| 亚洲高清视频一区二区| 欧美高清在线一区| 亚洲一区二区在线免费观看| 日韩视频永久免费| 欧美国产综合视频| 国产区欧美区日韩区| 久久精品国产视频| 蜜臀va亚洲va欧美va天堂| 在线亚洲欧美专区二区| 国产亚洲福利| 欧美激情一区二区三区在线视频观看 | 99精品国产在热久久婷婷| 亚洲午夜精品久久久久久app| 欧美激情中文不卡| 欧美激情一区二区在线| 久久综合亚州| 黄色亚洲免费| 亚洲国产精品免费| 欧美aⅴ99久久黑人专区| 亚洲人久久久| 久久久久久久成人| 亚洲国产一区二区三区a毛片| 久久国产成人| 国产亚洲午夜| 国产精品久久久久久久久久ktv | 欧美精品三级| 亚洲精品一级| 亚洲一区二区动漫| 亚洲一区在线播放| 欧美xx69| 性色av一区二区三区在线观看| 欧美日韩www| 久久久久久午夜| 欧美日韩福利在线观看| 久久久精品动漫| 午夜精品福利视频| 国产欧美综合在线| 久久国产一二区| 亚洲第一在线| 99视频精品免费观看| 午夜精品在线| 最新国产拍偷乱拍精品| 欧美在线观看视频在线 | 亚洲美女电影在线| 欧美专区日韩专区| 午夜精品久久久| 日韩视频免费在线观看| 欧美色中文字幕| 亚洲精品乱码| 亚洲欧美日本精品| 国产精自产拍久久久久久| 一区二区三区欧美| 99成人精品| 国产在线精品一区二区夜色| 久久久精品动漫| 亚洲国产精品嫩草影院| 欧美国产精品中文字幕| 欧美一区二区性| 日韩亚洲欧美一区二区三区| 欧美精品国产精品| 午夜视频久久久久久| 亚洲国产99精品国自产| 久久精品国产第一区二区三区| 曰本成人黄色| 欧美日韩国内| 久久精品官网| 亚洲欧美日韩一区二区| 久久综合网色—综合色88| 亚洲国产精品传媒在线观看| 国产精品va| 欧美国产精品人人做人人爱| 久久全球大尺度高清视频| 最新国产成人在线观看| 一区二区三区日韩精品视频| 亚洲国产精品一区制服丝袜| 黄色成人av| 欧美日韩国产综合视频在线| 暖暖成人免费视频| 亚洲欧美视频在线| 欧美在线二区| 欧美电影打屁股sp| 国产精品午夜在线| 亚洲第一偷拍| 亚洲一区二区在线| 香蕉免费一区二区三区在线观看| 亚洲专区欧美专区| 亚洲亚洲精品在线观看| 亚洲精品欧美| 亚洲欧美大片| 亚洲欧美怡红院| 怡红院av一区二区三区| 亚洲作爱视频| 亚洲免费影院| 久久综合伊人77777麻豆| 欧美伊人久久| 国产精品一二一区| 国产精品日韩专区| 亚洲三级影片| 欧美一区二区国产| 久久国内精品视频| 欧美日韩国产999| 国产一区二区三区免费在线观看| 亚洲国产一区二区三区在线播| 久久久www免费人成黑人精品| 欧美高清一区| 一区二区三区黄色| 欧美高清你懂得| 国产欧美日韩亚洲一区二区三区| 加勒比av一区二区| 日韩特黄影片| 久久综合九色欧美综合狠狠| 亚洲免费中文| 欧美日韩中文在线观看| 在线成人黄色| 中文亚洲视频在线| 久久久久免费| 久久三级福利| 亚洲电影免费观看高清完整版在线 | 国内精品伊人久久久久av一坑| 久久精品综合一区| 国产欧美日韩麻豆91| 亚洲精品日韩精品| 亚洲日本精品国产第一区| 牛牛影视久久网| 欧美精品激情在线观看| 亚洲第一搞黄网站| 久久影院午夜论| 久久久噜噜噜久久人人看| 欧美一区二区三区久久精品| 久久精品一区蜜桃臀影院| 精品不卡在线| 欧美国产精品久久| 久久影院午夜论| 亚洲国产日韩欧美一区二区三区| 国产欧美一区二区三区国产幕精品 | 激情五月综合色婷婷一区二区| 亚洲一级网站| 午夜精品免费| 亚洲第一中文字幕在线观看| 欧美精品一区视频| 一区二区三区 在线观看视| 一区二区三区精密机械公司| 精品99一区二区| 久久青草久久| 欧美日韩理论| 欧美在线观看天堂一区二区三区| 欧美一区观看| 国内精品久久久久久久影视蜜臀 | 亚洲欧美视频一区二区三区| 欧美精品久久99| 欧美好骚综合网| 欧美日韩精品不卡| 亚洲全部视频| 毛片av中文字幕一区二区| 羞羞漫画18久久大片| 欧美无乱码久久久免费午夜一区| 久久久久国产免费免费| 红桃视频成人| 女生裸体视频一区二区三区| 亚洲精品一区二区三区在线观看| 1024国产精品| 久久亚洲二区| 欧美二区在线播放| 亚洲人体一区| 欧美视频网站| 欧美黑人多人双交| 久久精品综合一区| 久久精品国产精品亚洲精品| 欧美特黄a级高清免费大片a级| 国产欧美日韩在线播放| 91久久久久久久久久久久久| 亚洲精品一区二区三区蜜桃久| 欧美激情欧美狂野欧美精品| 欧美一区91| 女人色偷偷aa久久天堂| 一区二区三区欧美激情| **欧美日韩vr在线| 欧美日本中文字幕| 亚洲欧美激情诱惑|