GDB: krok po kroku debugowanie programów C++ bez strachu przed segfault
GDB pozwala precyzyjnie zlokalizować miejsce awarii programu w ciągu 15–30 sekund. Zamiast dodawać print do każdej funkcji i ponownie kompilować, użyj debuggera, aby w czasie rzeczywistym sprawdzić stos wywołań i wartości zmiennych. Aby móc korzystać z informacji debugowania, kompiluj z flagami -g -O0:
g++ -g -O0 -o myprogram myprogram.cpp
Sprawdź obecność danych debugowania poleceniem file myprogram. Uruchom: gdb ./myprogram, a następnie run. W przypadku segfault GDB zatrzyma się i wskaże dokładne miejsce za pomocą backtrace (bt).
Przykład awarii w std::string::operator= z null-tem wskaźnikiem this jest widoczny od razu w stosie:
#0 0x... in std::string::operator= (this=0x0, ...)
#1 0x... in UserData::setName (...)
#2 0x... in main ()
Włącz czytelny format wyświetlania: set print pretty on i set print demangle on.
Punkty przerwania i krokowe wykonanie
Ustaw punkty przerwania, by kontrolować przebieg programu:
break main— na początku funkcjimainbreak program.cpp:42— na konkretnej liniibreak UserData::setName— przy wejściu do metodyinfo break— lista wszystkich punktów przerwania
W C++ dla przeciążonych funkcji podaj pełną sygnaturę: break print(int) lub break print(std::string). Zaawansowany sposób: rbreak ^.*::print$ dla wszystkich metod print pasujących do wyrażenia regularnego.
Nawigacja po kodzie:
| Komenda | Skrót | Działanie |
|---------|-------|----------|
| next | n | przejdź do następnej linii bez wejścia do funkcji |
| step | s | przejdź do następnej linii z wejściem do funkcji |
| finish | fin | wykonaj funkcję do końca |
| continue | c | kontynuuj do następnego punktu przerwania |
W C++ unikaj step na wywołaniach STL, takich jak push_back — użyj next, aby nie zagłębiać się w implementację bibliotek.
Przeglądanie zmiennych i obiektów
Polecenia do inspekcji stanu:
print variable_name— wartość zmiennejprint *pointer— zawartość przez wskaźnikprint vec.size()— wywołanie metodydisplay variable_name— automatyczne wyświetlanie po każdym krokuinfo locals— lokalne zmienneinfo args— argumenty funkcji
GDB poprawnie renderuje typy C++:
print myVector
$1 = std::vector of length 5, capacity 8 = {1, 2, 3, 4, 5}
print myString
$2 = "Hello, World!"
Jeśli widzisz <optimized out> — ponownie skompiluj z -O0. Bez flagi -g nazwy zmiennych nie będą widoczne.
Tryb TUI do wizualnego debugowania
Włącz tryb TUI: tui enable — ekran podzieli się na dwie części: u góry kod z podświetlonym bieżącym wierszem, u dołu polecenia. Sterowanie:
layout src— kod źródłowylayout asm— kod asemblerowylayout split— kod + asemblerlayout regs— rejestryCtrl + X, 2— dwa oknaCtrl + X, o— przełączanie między oknamiCtrl + X, a— wyjście z trybu TUI
Tryb TUI ułatwia nawigację, pokazując kontekst bez konieczności liczenia linii.
Najczęstsze problemy i rozwiązania
| Problem | Rozwiązanie |
|--------|-------------|
| <optimized out> | Kompiluj z -O0 |
| Brak nazw zmiennych | Użyj flagi -g |
| Lokalne zmienne nie są widoczne | Wykonaj info locals wewnątrz funkcji |
| Wektor pokazuje śmieci | Użyj print vec._M_impl._M_start w starszych wersjach libstdc++ |
Podstawowe polecenia dla programistów średniozaawansowanych
Opanuj te 10 poleceń, które wystarczą do 90% przypadków:
r— uruchomienie programub— ustawienie punktu przerwaniabt— stos wywołańn— nexts— stepfin— finishc— continuep— printi locals— lokalne zmienneq— wyjście z GDB
Co ważne
- Stos wywołań (
bt) rozwiązuje 70% problemów z segfault w kilka sekund, pokazując łańcuch wywołań aż domain. - Tryb TUI wizualizuje kod, redukując obciążenie poznawcze w dużych projektach.
- Flagi
-g -O0są wymagane; bez nich debugowanie jest niemożliwe. - Różnica między
nextastepma kluczowe znaczenie w C++ z STL — unikaj głębokiego przeszukiwania kodu bibliotek. displayorazinfo locals/argszapewniają pełną kontrolę nad stanem bez potrzeby dodatkowychprint.
— Editorial Team
Brak komentarzy.