繼續分享 5 個實用的 vs 除錯技巧
繼續分享 5 個實用的 vs 除錯技巧
原總結除錯vs2019vs前言
我在上一篇文章《5 個非常實用的 vs 除錯技巧》 中分享了 5
個我認為非常值得了解的 vs
除錯技巧,本週繼續分享 5
個很基礎但同樣實用的除錯技巧。
1. 條件斷點
作用簡介:
顧名思義,帶條件的斷點。滿足條件才中斷。條件斷點非常非常有用,使用得當,可以極大縮短我們除錯問題的時間。比如,有一個大迴圈,只在第 1024
次迴圈的時候有問題,我們如果單步(在 vs
中可以按 F10
),恐怕手得按殘了。又比如,我們想在特定條件下中斷。這時候條件斷點就是我們的救星。
2. 記憶體斷點
作用簡介:
顧名思義,針對記憶體設定的斷點。對於除錯邏輯復(hun)雜(luan)的程式,非常非常有用。比如,有一個全域性變數的值,在程式碼中有 N
memoryaccess-breakpoint
開啟方式:
除錯的時候,通過 除錯 -> 視窗 -> 斷點
即可開啟斷點視窗。在 vs2013
中對應的快捷鍵是 ctrl + alt + b
。開啟後可以 通過 新建 -> 新建資料訪問斷點(D)...
建立一個數據訪問斷點。
注意:
-
只有在程式中斷到偵錯程式的時候才允許新建資料訪問斷點。
-
輸入的是記憶體地址,可以直接輸入地址值,也可以通過
&
獲取地址。 -
vs
windbg
中的ba
命令更強大,感興趣的小夥伴兒可以檢視windbg
的幫助文件。
3. 異常開關
作用簡介:
異常最多分發兩輪,每輪都會優先分發給偵錯程式。如果偵錯程式沒處理,會繼續分發給異常處理函式。具體的分發過程可以參考《軟體除錯》。
比如,在下面的示例程式碼中。我在 ExceptionDemo()
中加上了 try {} catch {}
來捕獲一些異常。在 FunctionE()
中的某一行設定好斷點,如果一切正常是可以斷下來的。但是在 FunctionD()
中有可能丟擲異常,如果根據設定,vs
不處理這個異常,該異常會被 ExceptionDemo()
#include "stdafx.h"
#include <exception>
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;
}
}
exception
p.s.
雖然在程式碼中增加 try {} catch {}
有助於提高程式的健壯性,但有時候可能不利於我們發現問題,有些問題可能就被“默默”吞掉了。
開啟方式:
除錯的時候,通過 除錯 -> 異常(X)...
即可開啟異常設定對話方塊。在 vs2013
中對應的快捷鍵是 Ctrl + Alt + E
。
**注意:**只有在除錯的時候才能設定,不除錯的時候是看不到異常設定選單的。
4. 除錯時修改值
作用簡介:
假設我們正在除錯如下程式碼,跟蹤到了 if (bRich)
這一行,期待的 bRich
的值是 true
,而實際值是 false
。我們可以手動修改 bRich
的值為 true
來強行進入 if
分支,而不是 else
分支。(BTW,改完就真的有錢了麼?)
#include "stdafx.h"
#include <iostream>
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;
}
}
manual-modify-variable
小貼士:不僅可以通過懸浮視窗改變變數的值,我們還可以通過監視視窗
,記憶體視窗
等其它方式改變變數的值。
5. 拖動到指定位置執行
作用簡介:
相信,大家都有過手滑的情況,本來想的是單步步入(在 vs
中按 F11
)特定函式,沒想到卻按成了 F10
,華麗麗的錯過了想除錯的函式,這時候我們可以拖回來。又或者如上面的程式碼,當執行到第24
行的時候,發現 totalMoney
的值不是我們想要的,我們想重新回到前面跟蹤一下totalMoney
的值是怎麼來的,而我們又不想重新走一遍整個流程(因為可能很慢)。這時候我們可以手動拖動黃色小箭頭到第 22
行。請看下圖:
drag-to-specific-line
注意:
拖動功能是通過設定 eip(rip)
的值來實現的,拖動需謹慎,有些情況下可能導致程式崩潰!
測試工程下載地址
百度雲盤 連結: https://pan.baidu.com/s/1MSjUNPF-JHoY1t3l1xXFeg 提取碼: jew2
CSDN:https://download.csdn.net/download/xiaoyanilw/12640122
總結
本次介紹的 5
個除錯技巧雖然都很基礎,但是卻非常實用,而且使用頻率比較高。不知道你是否有所收穫呢?
參考資料
《軟體除錯》