Debugowanie kodu natywnego — Często zadawane pytania

Jak debugować naruszenia dostępu podczas uruchamiania programu poza debugerem programu Visual Studio?

Ustaw opcję Debugowanie just in time i uruchom program autonomicznie do momentu wystąpienia naruszenia dostępu. Następnie w oknie dialogowym Naruszenie dostępu możesz kliknąć przycisk Anuluj , aby uruchomić debuger.

Jak debugować naruszenie dostępu w języku C++?

Jeśli uzyskasz naruszenie dostępu w wierszu kodu, który wyłudza wiele wskaźników, może być trudno ustalić, który wskaźnik spowodował naruszenie dostępu. W programie Visual Studio okno dialogowe wyjątku jawnie nazywa wskaźnik, który spowodował naruszenie dostępu.

Na przykład, biorąc pod uwagę następujący kod, należy uzyskać naruszenie dostępu:

#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();

}

Jeśli uruchomisz ten kod w programie Visual Studio, powinno zostać wyświetlone następujące okno dialogowe wyjątku:

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

Jeśli nie możesz określić, dlaczego wskaźnik spowodował naruszenie dostępu, prześledź kod, aby upewnić się, że wskaźnik powodujący problem został przypisany poprawnie. Jeśli jest on przekazywany jako parametr, upewnij się, że został on przekazany poprawnie i nie tworzysz płytkiej kopii. Następnie sprawdź, czy wartości nie są przypadkowo zmieniane w programie, tworząc punkt przerwania danych dla danego wskaźnika, aby upewnić się, że nie jest modyfikowany w innym miejscu w programie. Aby uzyskać więcej informacji na temat punktów przerwania danych, zobacz sekcję punktów przerwania danych w temacie Używanie punktów przerwania.

Jak sprawdzić, czy wskaźniki uszkadzają adresy pamięci?

Sprawdź uszkodzenie stert. Większość uszkodzeń pamięci jest spowodowana uszkodzeniem stert. Spróbuj użyć narzędzia Global Flags (gflags.exe) lub pageheap.exe. Zobacz /windows-hardware/drivers/debugger/gflags-and-pageheap.

Aby dowiedzieć się, gdzie jest modyfikowany adres pamięci:

  1. Ustaw punkt przerwania danych na 0x00408000. Zobacz Ustawianie punktu przerwania zmiany danych (tylko natywny język C++).

  2. Po osiągnięciu punktu przerwania użyj okna Pamięć , aby wyświetlić zawartość pamięci rozpoczynającą się od 0x00408000. Aby uzyskać więcej informacji, zobacz Pamięć systemu Windows.

Jak sprawdzić, kto przekazuje nieprawidłową wartość parametru?

Aby rozwiązać ten problem:

  1. Ustaw punkt przerwania lokalizacji na początku funkcji.

  2. Kliknij prawym przyciskiem myszy punkt przerwania i wybierz pozycję Warunek.

  3. W oknie dialogowym Warunek punktu przerwania kliknij pole wyboru Warunek. Zobacz Zaawansowane punkty przerwania.

  4. Wprowadź wyrażenie, takie jak Var==3, w polu tekstowym, gdzie Var jest nazwą parametru zawierającego złą wartość i 3 jest nieprawidłową wartością przekazaną do niego.

  5. Wybierz przycisk radiowy True i kliknij przycisk OK.

  6. Teraz ponownie uruchom program. Punkt przerwania powoduje zatrzymanie programu na początku funkcji, gdy Var parametr ma wartość 3.

  7. Użyj okna Stos wywołań, aby znaleźć funkcję wywołującą i przejść do jej kodu źródłowego. Aby uzyskać więcej informacji, zobacz How to: Use the Call Stack Window (Instrukcje: używanie okna stosu wywołań).

Jak sprawdzić, które wywołanie funkcji nie powiodło się, jeśli było ono powtarzane wielokrotnie?

Przykład: Mój program kończy się niepowodzeniem przy wywołaniu określonej funkcji . CnvtV Program prawdopodobnie wywołuje tę funkcję kilkaset razy, zanim zakończy się niepowodzeniem. Jeśli ustawię punkt przerwania lokalizacji na CnvtV, program zatrzymuje się na każdym wywołaniu tej funkcji i nie chcę tego. Nie wiem, jakie warunki powodują niepowodzenie wywołania, więc nie mogę ustawić warunkowego punktu przerwania. Co mogę zrobić?

Możesz ustawić punkt przerwania w funkcji z polem Liczba trafień na wartość tak wysoką, że nigdy nie zostanie osiągnięty. W takim przypadku, ponieważ uważasz, że funkcja CnvtV jest wywoływana kilkaset razy, możesz ustawić wartość Liczba trafień na 1000 lub więcej. Następnie uruchom program i poczekaj na niepowodzenie wywołania. Gdy zakończy się to niepowodzeniem, otwórz okno Punkty przerwania i przyjrzyj się liście punktów przerwania. Zostanie wyświetlony punkt CnvtV przerwania, po którym następuje liczba trafień i liczba pozostałych iteracji:

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

Teraz wiesz, że funkcja nie powiodła się podczas wywołania 101. Jeśli zresetujesz punkt przerwania z liczbą trafień 101 i ponownie uruchomisz program, program zatrzyma wywołanie, które CnvtV spowodowało jego niepowodzenie.

Gdzie można sprawdzić kody błędów Win32?

WINERROR. H w katalogu INCLUDE domyślnej instalacji systemu zawiera definicje kodu błędu dla funkcji interfejsu API Win32.

Kod błędu można wyszukać, wpisując kod w oknie Czujka lub w oknie dialogowym QuickWatch . Na przykład:

0x80000004,hr

Jak zachować fokus podczas przechodzenia przez aplikację?

Przykład: Mój program ma problem z aktywacją okien. Przechodzenie przez program z debugerem zakłóca moją zdolność do odtworzenia problemu, ponieważ mój program ciągle traci fokus. Czy istnieje jakiś sposób, aby uniknąć utraty koncentracji uwagi?

Jeśli masz drugi komputer, użyj zdalnego debugowania. Program można obsługiwać na komputerze zdalnym podczas uruchamiania debugera na hoście. Aby uzyskać więcej informacji, zobacz How to: Select a Remote Computer (Instrukcje: wybieranie komputera zdalnego).

Jak można debugować funkcje interfejsu API systemu Windows?

Aby ustawić punkt przerwania w funkcji interfejsu API systemu Windows z załadowanymi symbolami NT:

  • W punkcie przerwania funkcji wprowadź nazwę funkcji wraz z nazwą biblioteki DLL, w której znajduje się funkcja (zobacz operator kontekstu). W 32-bitowym kodzie użyj ozdobionej formy nazwy funkcji. Aby ustawić punkt przerwania w usłudze MessageBeep, na przykład należy wprowadzić następujące polecenie.

    {,,USER32.DLL}_MessageBeep@4
    

    Aby uzyskać nazwę ozdobioną, zobacz Wyświetlanie nazw ozdobionych.

    Możesz przetestować nazwę ozdobioną i wyświetlić ją w kodzie dezasemblacji. Podczas wstrzymania funkcji w debugerze programu Visual Studio kliknij prawym przyciskiem myszy funkcję w edytorze kodu lub oknie stosu wywołań i wybierz polecenie Przejdź do dezasemblacji.

  • W 64-bitowym kodzie można użyć nazwy nieukodowanej.

    {,,USER32.DLL}MessageBeep
    

Następne kroki

Aby dowiedzieć się więcej na temat debugowania kodu natywnego w programie Visual Studio, skorzystaj z następujących linków: