디버거 사용법
디버거의 기본 개념
디버깅은 프로그램의 오류를 찾아 수정하는 과정으로, 효율적인 소프트웨어 개발에 필수적인 기술입니다.
이 절에서는 C++ 프로그램 디버깅을 위한 다양한 도구와 기법을 자세히 살펴보고, 실습을 통해 이해를 깊이 있게 할 것입니다.
디버거는 프로그램의 실행을 제어하고 내부 상태를 검사할 수 있게 해주는 도구입니다. 주요 기능은 다음과 같습니다.
- 브레이크포인트 설정
- 단계별 실행 (Step Over, Step Into, Step Out)
- 변수 값 검사
- 콜 스택 확인
- 메모리 내용 확인
GDB (GNU Debugger) 심화
GDB는 강력한 명령줄 디버거로, 다양한 고급 기능을 제공합니다.
조건부 브레이크포인트
특정 조건이 만족될 때만 실행을 중단하도록 설정할 수 있습니다.
이 명령은 10번 줄에 브레이크포인트를 설정하지만, 변수 i
가 5일 때만 실행을 중단합니다.
워치포인트
특정 변수의 값이 변경될 때 실행을 중단하도록 설정할 수 있습니다.
이 명령은 변수 x
의 값이 변경될 때마다 실행을 중단합니다.
역방향 디버깅
GDB는 프로그램의 실행을 거꾸로 되돌릴 수 있는 기능을 제공합니다.
이 기능을 사용하면 버그의 원인을 추적하기 쉬워집니다.
Python 스크립팅
GDB는 Python 스크립트를 통해 확장할 수 있습니다. 예를 들어, 사용자 정의 명령을 만들 수 있습니다.
이 스크립트를 GDB에 로드하면 pstack
명령을 사용할 수 있게 됩니다.
LLDB 사용법
LLDB는 LLVM 프로젝트의 일부로, macOS에서 기본 디버거로 사용됩니다.
GDB와 유사한 기능을 제공하지만 몇 가지 차이점이 있습니다.
LLDB 기본 명령어
b
또는breakpoint set
: 브레이크포인트 설정r
또는run
: 프로그램 실행n
또는next
: 다음 줄로 이동 (함수 호출 시 함수 내부로 들어가지 않음)s
또는step
: 다음 줄로 이동 (함수 호출 시 함수 내부로 들어감)p
또는print
: 변수 값 출력bt
또는thread backtrace
: 콜 스택 표시c
또는continue
: 다음 브레이크포인트까지 실행q
또는quit
: LLDB 종료
LLDB 고급 기능
LLDB는 강력한 명령 구문 분석 기능을 제공합니다.
예를 들어,
이 명령은 foo.c 파일의 12번 줄에 조건부 브레이크포인트를 설정합니다.
Visual Studio Code에서의 디버깅
Visual Studio Code는 다양한 언어와 플랫폼을 지원하는 강력한 에디터입니다.
C++ 디버깅을 위해 다음과 같은 기능을 제공합니다.
launch.json 설정
디버깅 구성을 위해 launch.json
파일을 사용합니다.
VS Code 디버깅 기능
- 브레이크포인트 설정 : 라인 번호 왼쪽을 클릭
- 디버깅 시작 : F5
- Step Over : F10
- Step Into : F11
- Step Out : Shift+F11
- 변수 검사 : 디버그 뷰의 변수 섹션 또는 마우스 오버
메모리 오류 디버깅 도구
Valgrind 심화
Valgrind의 Memcheck 도구는 다양한 메모리 오류를 탐지할 수 있습니다.
이 명령은 모든 종류의 메모리 누수를 체크하고, 초기화되지 않은 값의 사용을 추적합니다.
AddressSanitizer 심화
AddressSanitizer는 다양한 메모리 오류를 탐지할 수 있습니다.
이 명령으로 컴파일하면 힙 버퍼 오버플로우, 스택 버퍼 오버플로우, 전역 버퍼 오버플로우, use-after-free, use-after-return, 초기화되지 않은 메모리 읽기 등을 탐지할 수 있습니다.
고급 디버깅 기법
코어 덤프 분석
프로그램이 비정상 종료될 때 생성되는 코어 덤프를 분석하여 문제의 원인을 찾을 수 있습니다.
원격 디버깅
GDB를 사용하여 원격 시스템에서 실행 중인 프로그램을 디버깅할 수 있습니다.
- 원격 시스템에서
- 로컬 시스템에서
멀티스레드 프로그램 디버깅
GDB에서 멀티스레드 프로그램을 디버깅할 때 유용한 명령어들
info threads
: 모든 스레드 정보 표시thread apply all bt
: 모든 스레드의 백트레이스 표시set scheduler-locking on
: 현재 스레드만 실행되도록 설정
실습 : 복잡한 버그 찾기
다음 코드에는 여러 가지 버그가 숨어 있습니다.
디버거를 사용하여 이 버그들을 찾아내고 수정해보세요.
연습 문제
- GDB를 사용하여 세그멘테이션 폴트가 발생하는 프로그램을 디버깅하세요. 오류의 정확한 위치와 원인을 찾아내세요.
- 데이터 레이스 조건이 있는 멀티스레드 프로그램을 작성하고, 이를 Thread Sanitizer를 사용하여 디버깅하세요.
- 메모리 누수가 있는 프로그램을 작성하고, Valgrind를 사용하여 누수를 찾아내고 수정하세요.
- 재귀 함수에서 발생하는 스택 오버플로우를 디버거를 사용하여 분석하세요. 콜 스택을 검사하고 문제의 원인을 설명하세요.
참고자료
- "Debugging with GDB : The GNU Source-Level Debugger" by Richard M. Stallman, Roland Pesch, Stan Shebs
- "LLDB Debugging Guide" - Apple Developer Documentation
- "Advanced C and C++ Compiling" by Milan Stevanovic
- "Windows Debugging : Practical Foundations" by Dmitry Vostokov
- "The Art of Debugging with GDB, DDD, and Eclipse" by Norman Matloff and Peter Jay Salzman
- "Intel 64 and IA-32 Architectures Software Developer's Manual"
- "Valgrind 3.x Documentation"
- "AddressSanitizer for x86/Linux : Installation and Usage"
- "Visual Studio Code C++ Documentation"
- "Effective Debugging : 66 Specific Ways to Debug Software and Systems" by Diomidis Spinellis