機器碼偵錯 FAQ

在 Visual Studio 偵錯工具外執行我的程式時,如何偵錯存取違規?

設定 偵錯選項並獨立執行您的程式,直到發生存取違規為止。 然後,在 [存取違規] 對話方塊中,您可以按一下 [取消] 來啟動偵錯工具。

如何偵錯 C++ 存取違規?

如果您在對多個指標取值的程式碼行上取得存取違規,可能很難找出哪個指標造成存取違規。 在 Visual Studio 中,例外狀況對話方塊會明確地指出造成存取違規的指標。

例如,您應該會在下列程式碼中取得存取違規:

#include <iostream>
using namespace std;

class ClassC {
public:
  void printHello() {
    cout << "hello world";
  }
};

class ClassB {
public:
  ClassC* C;
  ClassB() {
    C = new ClassC();
  }
};

class ClassA {
public:
  ClassB* B;
  ClassA() {
    // Uncomment to fix
    // B = new ClassB();
  }
};

int main() {
  ClassA* A = new ClassA();
  A->B->C->printHello();

}

如果您在 Visual Studio 中執行這段程式碼,您應該會看到下列例外狀況對話方塊:

Screenshot of a Microsoft Visual Studio exception dialog, showing a read access violation for 'A->B was nullptr'. The Break button is selected.

如果您無法判斷指標造成存取違規的原因,請追蹤整個程式碼,確定已正確指派造成問題的指標。 如果將指標當作參數傳遞,請確定其已正確地傳遞,而且您沒有不小心建立淺層複製。 然後確認這些值未在程式中的某處意外變更,方法是為有問題的指標建立資料中斷點,以確定此指標未在程式中的其他位置修改。 如需資料中斷點的詳細資訊,請參閱 Using Breakpoints中的<資料中斷點>一節。

如何確認我的指標是否會損毀記憶體位址?

檢查堆積損毀。 大部分的記憶體損毀是由於堆積損毀所造成。 請嘗試使用全域旗標公用程式 (gflags.exe) 或 pageheap.exe。 請參閱 /windows-hardware/drivers/debugger/gflags-and-pageheap

若要找出記憶體位址遭修改的位置:

  1. 在 0x00408000 設定資料中斷點。 請參閱設定資料變更中斷點 (僅限原生 C++)

  2. 當您遇到中斷點時,使用 [記憶體] 視窗來檢視從 0x00408000 開始的記憶體內容。 如需詳細資訊,請參閱記憶體視窗

如何發現誰傳錯參數值?

若要解決此問題:

  1. 在函式的開頭設定位置中斷點。

  2. 以滑鼠右鍵按一下中斷點並選取 [條件]

  3. 在 [中斷點條件] 對話方塊中,按一下 [條件] 核取方塊。 請參閱進階中斷點

  4. 在文字方塊中輸入運算式,例如 Var==3;其中 Var 是含有錯誤值的參數名稱,而 3 則是傳入的錯誤值。

  5. 選取 [為 True] 選項按鈕,然後按一下 [確定] 按鈕。

  6. 現在再次執行程式。 當 Var 參數的值是 3 時,中斷點會造成程式暫止在函式的開頭。

  7. 然後您可以使用 [呼叫堆疊] 視窗來找出呼叫函式並且巡覽原始程式碼。 如需詳細資訊,請參閱如何:使用呼叫堆疊視窗

呼叫函式好幾百次時,如何判斷是哪一個呼叫失敗?

範例:我的程式在呼叫特定函式 CnvtV 時失敗。 失敗之前,程式大概會呼叫此函式幾百次。 如果我在 CnvtV 上設定一個中斷點,程式會在每次呼叫此函式時停止,但是我不要這樣。 我不知道什麼條件會造成呼叫失敗,因此我無法設定條件中斷點。 我能做什麼?

您可以在函式上設定一個 [叫用次數] 欄位值永遠無法遇到的中斷點。 在這種情況下,因為您相信函式 CnvtV 會遭呼叫幾百次,請將 [叫用次數] 設為 1000 或更高。 接著執行程式並且等候它失敗。 當程式失敗時,開啟 [中斷點] 視窗並且查看中斷點的清單。 您在 CnvtV 上設定的中斷點會出現,其後跟著叫用次數和未完成的重複運算次數:

CnvtV(int) (no condition) when hit count is equal to 1000 (currently 101)

現在您已經知道函式會在第 101 次呼叫時失敗。 如果您以叫用次數 101 重設中斷點並且再次執行程式,程式會在上次造成失敗的 CnvtV 呼叫處停止。

哪裡可以查看 Win32 錯誤碼?

WINERROR.H 您的預設系統安裝 INCLUDE 目錄裡的 WINERROR.H 包含 Win32 API 函式的錯誤碼定義。

您可以在 [監看式] 視窗或 [快速監看式] 對話方塊中鍵入程式碼來查看錯誤碼。 例如:

0x80000004,hr

逐步執行我的應用程式時,如何保持焦點?

範例:我的程式有視窗啟動的問題。 要重現問題時,以偵錯工具逐步執行程式會帶來干擾,因為程式會一直失焦。 有什麼方法可以避免失去焦點嗎?

如果您有第二台電腦,使用遠端偵錯。 當您在本機上執行偵錯工具時,您可以在遠端電腦上操作程式。 如需詳細資訊,請參閱如何:選取遠端電腦

如何對 Windows API 函式進行偵錯?

若要在含載入之 NT 符號的 Windows API 函式上設定中斷點:

  • 函式中斷點中,輸入加上函式所在 DLL 名稱的函式名稱 (請參閱內容運算子)。 在 32 位元程式碼中,請使用函式名稱的裝飾形式。 例如,若要在 MessageBeep 上設定中斷點,您必須輸入下列程式碼。

    {,,USER32.DLL}_MessageBeep@4
    

    若要取得裝飾名稱,請參閱檢視裝飾名稱

    您可以測試裝飾名稱,並在反組譯碼程式碼中檢視它。 在 Visual Studio 偵錯工具的函式上暫停時,以滑鼠右鍵按一下程式碼編輯器中的函式,或呼叫堆疊視窗,然後選擇 [前往反組譯碼]

  • 在 64 位程式碼中,您可以使用未裝飾名稱。

    {,,USER32.DLL}MessageBeep
    

下一步

您可以使用下列連結深入了解 Visual Studio 中的機器碼偵錯: