이 Part에서 다루는 것
- 브레이크포인트/Step 실행/F11/F10으로 흐름을 통제하는 방법
- 호출 스택으로 “누가 이 함수를 호출했는지” 역추적하는 방법
- Watch/메모리 창으로 가설을 숫자와 주소로 검증하는 방법
학습 목표
- 버그 유형에 따라 어떤 디버깅 도구를 먼저 써야 할지 선택할 수 있다.
- “멈춘 위치”와 “원인 시작점”을 구분해 호출 스택으로 거슬러 올라갈 수 있다.
- 눈대중이 아니라 Watch/메모리 창으로 근거를 확인하는 습관을 갖는다.
브레이크포인트 (F9): 의심 지점에서 실행 멈추기
- 브레이크포인트는 “프로그램을 원하는 줄에서 멈춰 상태를 관찰”하는 도구입니다.
- 증상이 반복될 때는 조건부 중단점으로 잡음 없이 필요한 순간만 멈춥니다.
- 예:
k1->_hp < 0, slot == 17 등
실전 팁:
- 무조건 처음 줄에 걸기보다, “값이 깨졌을 가능성이 큰 경계 지점”에 먼저 겁니다.
F10 / F11 / Shift+F11: 실행 흐름 제어
- F10 (Step Over): 현재 줄 실행, 함수 내부로는 들어가지 않음
- F11 (Step Into): 현재 줄 실행 + 함수 내부로 들어감
- Shift+F11 (Step Out): 현재 함수 실행을 마치고 호출한 곳으로 복귀
선택 기준:
- 원인을 아직 모르면 F10으로 넓게 본다
- 특정 함수가 의심되면 F11로 내부를 판다
- 내부가 아니라고 판단되면 Shift+F11로 빨리 빠져나온다
호출 스택 (Call Stack): “어디서 왔는가” 추적
- 현재 중단된 함수만 보면 “왜 여기 왔는지”를 모를 때가 많습니다.
- 호출 스택을 보면
main -> ... -> CrashFunc처럼 호출 경로를 확인할 수 있습니다.
예:
PrintInfo()에서 크래시
- 호출 스택을 올라가보니
knights[i]->PrintInfo()에서 i가 범위를 벗어남
핵심:
- 크래시 줄은 “결과”일 때가 많고, 호출 스택 상위 프레임이 “원인”인 경우가 많습니다.
실행 위치 이동(드래그 / Set Next Statement): 재검증 보조용
- 디버깅 중 실행 화살표를 이동해 특정 구간을 다시 볼 수 있습니다.
- 다만 초기화/부작용 코드를 건너뛰거나 중복 실행하면 상태가 왜곡될 수 있습니다.
규칙:
- “원인 탐색용 임시 실험”으로만 쓰고,
- 최종 결론은 정상 실행 흐름에서 다시 검증합니다.
조사식 (Watch): 가설을 수치로 확인
- 의심 변수/표현식을 Watch에 넣고, 스텝 실행마다 변화를 확인합니다.
- 예:
k1->_hp, index, player->_target, count <= maxCount 등
핵심:
- “보일 것 같다”가 아니라 “실제로 값이 어떻게 변하는지”를 근거로 판단해야 합니다.
메모리 창: 주소 단위로 사실 확인
- 포인터 주소를 기준으로 실제 메모리 바이트를 확인할 수 있습니다.
- UAF/버퍼 오염/잘못된 캐스팅 같은 저수준 버그에서 강력합니다.
주의:
- 디버그 빌드에서 보이는 패턴값(예:
0xCDCDCDCD)은 디버거 보조 패턴일 뿐,
릴리즈 빌드에서도 같은 값이 나온다는 보장은 없습니다.