繼續(xù)分享 5 個實用的 vs 調(diào)試技巧
前言
我在上一篇文章?《5 個非常實用的 vs 調(diào)試技巧》 中分享了 5 個我認為非常值得了解的 vs 調(diào)試技巧,本周繼續(xù)分享 5 個很基礎(chǔ)但同樣實用的調(diào)試技巧。
1. 條件斷點
作用簡介:
顧名思義,帶條件的斷點。滿足條件才中斷。條件斷點非常非常有用,使用得當,可以極大縮短我們調(diào)試問題的時間。比如,有一個大循環(huán),只在第 1024 次循環(huán)的時候有問題,我們?nèi)绻麊尾剑ㄔ?vs 中可以按 F10),恐怕手得按殘了。又比如,我們想在特定條件下中斷。這時候條件斷點就是我們的救星。

2. 內(nèi)存斷點
作用簡介:
顧名思義,針對內(nèi)存設(shè)置的斷點。對于調(diào)試邏輯復(hun)雜(luan)的程序,非常非常有用。比如,有一個全局變量的值,在代碼中有 N 個地方會改動它,在調(diào)試程序的時候,不知道這個全局變量在哪里被改變了,如果能在改動的那一刻中斷下來該有多好啊!這可是內(nèi)存斷點的專長!
打開方式:
調(diào)試的時候,通過 調(diào)試 -> 窗口 -> 斷點 即可打開斷點窗口。在 vs2013 中對應(yīng)的快捷鍵是 ctrl + alt + b 。打開后可以 通過 新建 -> 新建數(shù)據(jù)訪問斷點(D)... 創(chuàng)建一個數(shù)據(jù)訪問斷點。
注意:
只有在程序中斷到調(diào)試器的時候才允許新建數(shù)據(jù)訪問斷點。
輸入的是內(nèi)存地址,可以直接輸入地址值,也可以通過
&獲取地址。vs好像只支持指定的內(nèi)存范圍的值發(fā)生變化時才中斷。windbg中的ba命令更強大,感興趣的小伙伴兒可以查看windbg的幫助文檔。
3. 異常開關(guān)
作用簡介:
異常最多分發(fā)兩輪,每輪都會優(yōu)先分發(fā)給調(diào)試器。如果調(diào)試器沒處理,會繼續(xù)分發(fā)給異常處理函數(shù)。具體的分發(fā)過程可以參考《軟件調(diào)試》。
比如,在下面的示例代碼中。我在 ExceptionDemo() 中加上了 try {} catch {} ?來捕獲一些異常。在 FunctionE() 中的某一行設(shè)置好斷點,如果一切正常是可以斷下來的。但是在 FunctionD() 中有可能拋出異常,如果根據(jù)設(shè)置,vs 不處理這個異常,該異常會被 ExceptionDemo() 處理,還沒運行到設(shè)置斷點的地方就被異常改變了執(zhí)行流程。
#include?"stdafx.h"
#include?
bool?application_quit?=?false;
int?g_runningLoop?=?0;
void?FunctionA();
void?FunctionB();
void?FunctionC();
void?FunctionD();
void?FunctionE();
void?ExceptionDemo()
{
????try
????{
????????while?(!application_quit)
????????{
????????????FunctionA();
????????}
????}
????catch?(std::exception)
????{
????}
}
void?FunctionA()?{?FunctionB();?}
void?FunctionB()?{?FunctionC();?}
void?FunctionC()?{?FunctionD();?}
void?FunctionD()
{
????if?(++g_runningLoop?>?6)
????{
????????throw?std::exception("too?many?loops!");
????}
????FunctionE();
}
void?FunctionE()
{
????if?(g_runningLoop?>?10)
????{
????????application_quit?=?true;
????}
}p.s.?雖然在代碼中增加?try {} catch {}?有助于提高程序的健壯性,但有時候可能不利于我們發(fā)現(xiàn)問題,有些問題可能就被“默默”吞掉了。
打開方式:
調(diào)試的時候,通過 調(diào)試 -> 異常(X)... 即可打開異常設(shè)置對話框。在 vs2013 中對應(yīng)的快捷鍵是 Ctrl + Alt + E。
注意:只有在調(diào)試的時候才能設(shè)置,不調(diào)試的時候是看不到異常設(shè)置菜單的。
4. 調(diào)試時修改值
作用簡介:
假設(shè)我們正在調(diào)試如下代碼,跟蹤到了 if (bRich) 這一行,期待的 bRich 的值是 true,而實際值是 false。我們可以手動修改 bRich 的值為 true 來強行進入 if 分支,而不是 else 分支。(BTW,改完就真的有錢了么?)
#include?"stdafx.h"
#include?
bool?HaveIMakeEnoughMoney()
{
????return?false;
}
void?ManualModifyValueDemo()
{
????auto?bRich?=?HaveIMakeEnoughMoney();
????if?(bRich)
????{
????????std::cout?<"Finally,?I'm?rich!"?<std::endl;
????}
????else
????{
????????std::cout?<"Oops,?I'm?still?poor!"?<std::endl;
????}
}

小貼士:不僅可以通過懸浮窗口改變變量的值,我們還可以通過監(jiān)視窗口,內(nèi)存窗口等其它方式改變變量的值。
5. 拖動到指定位置執(zhí)行
作用簡介:
相信,大家都有過手滑的情況,本來想的是單步步入(在 vs 中按 F11)特定函數(shù),沒想到卻按成了 F10,華麗麗的錯過了想調(diào)試的函數(shù),這時候我們可以拖回來。又或者如上面的代碼,當執(zhí)行到第24行的時候,發(fā)現(xiàn) totalMoney 的值不是我們想要的,我們想重新回到前面跟蹤一下totalMoney 的值是怎么來的,而我們又不想重新走一遍整個流程(因為可能很慢)。這時候我們可以手動拖動黃色小箭頭到第 22 行。
注意:
拖動功能是通過設(shè)置 eip(rip) 的值來實現(xiàn)的,拖動需謹慎,有些情況下可能導致程序崩潰!
測試工程下載地址
百度云盤?鏈接: https://pan.baidu.com/s/1MSjUNPF-JHoY1t3l1xXFeg 提取碼: jew2
CSDN:https://download.csdn.net/download/xiaoyanilw/12640122
總結(jié)
本次介紹的 5 個調(diào)試技巧雖然都很基礎(chǔ),但是卻非常實用,而且使用頻率比較高。不知道你是否有所收獲呢?
參考資料
《軟件調(diào)試》
感謝你的贊和在看![]()
