數(shù)據(jù)斷點(diǎn)
注意,這個(gè)技巧僅對(duì)C++程序調(diào)試有效(或者說native程序),而且你只能在中斷模式下才能設(shè)置數(shù)據(jù)斷點(diǎn),另外你還只能在本機(jī)設(shè)置數(shù)據(jù)斷點(diǎn)。
上一節(jié)的例子里,我們提到了,有的時(shí)候一個(gè)全局變量被修改了以后,你可能都找不到它是什么時(shí)候被修改的,于是夜已深,人已寐,你還在辛苦地調(diào)試到底是哪個(gè)鬼地方把這個(gè)變量的值修改了。F11, F10,……,SHIFT + F11,……,F5,靠,調(diào)過了,重來,F11,F10,……
這種情況下,數(shù)據(jù)斷點(diǎn)就很有用了,Visual Studio允許你在變量被修改的時(shí)候,中斷程序的執(zhí)行,是不是很酷?
默認(rèn)情況下,你是找不到數(shù)據(jù)斷點(diǎn)這個(gè)菜單的,需要執(zhí)行下面的步驟把它拉出來:
- 打開你要調(diào)試的項(xiàng)目。
- 點(diǎn)擊Visual Studio菜單欄里面的“工具(Tools)”—“自定義(Customize…)”。然后在“自定義(Customize…)”窗口中選擇“命令(Commands)”頁(yè)簽里面的“種類(Categories)”列表框里的“調(diào)試(Debug)”,找到“新數(shù)據(jù)斷點(diǎn)(New Data Breakpoint)”,將它拖到菜單欄里面相應(yīng)的位置。
然后打開或者創(chuàng)建一個(gè)C++項(xiàng)目,我們以下面的源代碼為例子:
#include "stdafx.h"
int g_Variable = 0;
int _tmain(int argc, _TCHAR* argv[])
{
printf("Before modifying data breakpoints"n");
g_Variable = 1;
printf("After modifying data breakpoints"n");
return 0;
}
我們現(xiàn)在要Visual Studio在更改g_Variable的時(shí)候中斷程序的執(zhí)行。
1、單擊F11,這樣程序就會(huì)在_tmain函數(shù)里面中斷了,我們也就有機(jī)會(huì)設(shè)置數(shù)據(jù)斷點(diǎn)了。
2、點(diǎn)擊菜單里面的“新數(shù)據(jù)斷點(diǎn)(New Data Breakpoint)”。注意,數(shù)據(jù)斷點(diǎn)是通過監(jiān)視內(nèi)存地址某一段區(qū)域更改來實(shí)現(xiàn)的,因此你必須提供一個(gè)內(nèi)存地址(或者說就是指針吧),這里g_Variable是一個(gè)整形變量,因此你需要使用“&g_Variable”的形式來創(chuàng)建一個(gè)數(shù)據(jù)斷點(diǎn),因?yàn)檎蔚?/span> 大小是4個(gè)字節(jié),因此數(shù)據(jù)斷點(diǎn)監(jiān)視的區(qū)域是4個(gè)字節(jié),如下圖所示:
3、繼續(xù)程序的執(zhí)行,這時(shí)會(huì)彈出一個(gè)對(duì)話框,告訴你有一個(gè)內(nèi)存地址的內(nèi)容發(fā)生了變化(說明我們的數(shù)據(jù)斷點(diǎn)生效了),這時(shí)代碼行指向的是數(shù)據(jù)被修改的下一行代碼,為什么會(huì)是下一行代碼,下一篇文章會(huì)講到:
呃,為什么數(shù)據(jù)斷點(diǎn)只能在C++/C程序中才能設(shè)置?是因?yàn)橥泄艽a有垃圾回收。而數(shù)據(jù)斷點(diǎn)的執(zhí)行原理應(yīng)該是Windows內(nèi)存管理里面的Guard Pages概念和VirtualProtectEx函數(shù)的實(shí)現(xiàn)。這個(gè)概念可以自己去查MSDN的內(nèi)存管理方面的文檔。