1. 필수 디버깅 단축키 (Keyboard Shortcuts)
효율적인 디버깅을 위해 반드시 숙지해야 할 핵심 단축키입니다. (설정: 일반 개발 설정 기준)
기능 | 단축키 | 설명 |
실행 / 계속 | F5 | 디버깅 시작 또는 다음 중단점까지 계속 실행 |
디버깅 중지 | Shift + F5 | 현재 디버깅 세션 즉시 종료 |
다시 시작 | Ctrl + Shift + F5 | 디버깅을 종료하고 즉시 다시 시작 (Rebuild 아님) |
중단점 설정/해제 | F9 | 커서 위치에 중단점(Breakpoint) 토글 |
프로시저 단위 실행 | F10 (Step Over) | 함수 내부로 들어가지 않고 한 줄씩 실행 |
한 단계씩 코드 실행 | F11 (Step Into) | 함수 호출 시 해당 함수 내부로 진입하여 실행 |
프로시저 나가기 | Shift + F11 (Step Out) | 현재 함수를 끝까지 실행하고 호출한 곳으로 리턴 |
커서까지 실행 | Ctrl + F10 | 현재 마우스 커서가 있는 줄까지 코드를 실행하고 멈춤 (매우 유용) |
2. 조사식(Watch) 창 고급 기능
단순히 변수 값만 보는 것이 아니라, 포맷 변경, 수식 계산, 특수 변수를 활용할 수 있습니다.
A. 형식 지정자 (Format Specifiers)
변수명 뒤에 ,와 코드를 붙여 원하는 형태로 값을 확인합니다. (특히 비트 연산 디버깅에 필수)
지정자 (C/C++) | 지정자 (C#) | 설명 | 예시 (입력 → 출력) |
d | d | 10진수 정수 | flag,d $\rightarrow$ 10 |
h 또는 x | h 또는 x | 16진수 (Hex) | flag,x $\rightarrow$ 0x0A |
b | b (VS2022+) | 2진수 (Binary) | flag,b $\rightarrow$ 0b00001010 (비트 플래그 확인 시 최적) |
s | nq (No Quotes) | 문자열 (따옴표 제거) | str,nq $\rightarrow$ Hello |
mq | - | 메모리 뷰 확인 | 문자열 포인터 등의 메모리 덤프 확인 |
B. 의사 변수 (Pseudo-variables)
디버거가 제공하는 특수 변수로, 현재 상태를 추적할 때 유용합니다.
•
$err (또는 $hr): 마지막으로 발생한 오류 코드(GetLastError 값)를 보여줍니다. API 호출 실패 원인을 찾을 때 유용합니다.
•
$returnValue: 방금 실행된 함수의 반환값을 보여줍니다. (변수에 받지 않고 실행만 했을 때 확인 용도)
•
$exception: (C#) 현재 발생한 예외 객체의 정보를 보여줍니다. catch 블록 내부에서 유용합니다.
3. 스마트 중단점 (Advanced Breakpoints)
단순히 멈추는 것이 아니라, 조건이나 로깅을 위해 사용합니다. (빨간 점 우클릭 조건/작업)
1.
조건부 중단점 (Conditional Breakpoint):
•
특정 조건이 true일 때만 멈춥니다.
•
예: i == 1024 (루프가 1024번 돌았을 때만 멈춤)
•
예: (flags & 0x04) != 0 (특정 비트가 셋팅되었을 때만 멈춤)
2.
적중 횟수 (Hit Count):
•
이 중단점을 N번째 지나갈 때 멈추게 설정합니다. 반복문 디버깅에 탁월합니다.
3.
추적점 (Tracepoint / 액션):
•
코드를 멈추지 않고 출력 창에 메시지를 로그로 남깁니다.
•
Console.WriteLine을 코드에 넣었다 뺐다 할 필요 없이 디버거로 로그를 찍을 수 있습니다.
4. 멀티스레드(Multi-thread) 디버깅
병렬 처리 코드를 디버깅할 때 다른 스레드의 간섭을 막거나 흐름을 파악하는 도구입니다.
A. 스레드 창 (Threads Window)
•
메뉴: 디버그 > 창 > 스레드 (Ctrl + Alt + H)
•
기능: 현재 실행 중인 모든 스레드 목록을 보여줍니다.
•
활용: 특정 스레드를 더블 클릭하여 해당 스레드의 호출 스택(Call Stack)으로 이동할 수 있습니다.
B. 스레드 정지/해제 (Freeze & Thaw)
•
상황: 스레드 A를 디버깅 중인데, 스레드 B가 계속 실행되어 데이터를 변경하거나 로그를 어지럽힐 때.
•
방법: 스레드 창에서 스레드 B를 우클릭 동결(Freeze).
•
효과: 스레드 B는 일시 정지되어 실행되지 않습니다. 디버깅이 끝나면 **해동(Thaw)*하여 다시 실행합니다.
C. 병렬 스택 (Parallel Stacks)
•
메뉴: 디버그 > 창 > 병렬 스택
•
기능: 모든 스레드의 호출 스택을 하나의 다이어그램으로 시각화합니다.
•
활용: 교착 상태(Deadlock)가 발생했을 때, 어떤 스레드들이 어디서 서로를 기다리고 있는지 한눈에 파악하기 좋습니다.
5. 로우 레벨 디버깅 (메모리 & 레지스터)
A. 메모리 창 (Memory Window)
•
메뉴: 디버그 > 창 > 메모리
•
기능: RAM의 특정 주소 값을 Raw Data(Hex)로 보여줍니다.
•
활용: 포인터 변수가 가리키는 실제 데이터 확인, 구조체 패딩 확인, 버퍼 오버플로우 흔적 찾기.
B. 레지스터 창 (Registers)
•
메뉴: 디버그 > 창 > 레지스터
•
기능: CPU 레지스터(EAX, RSP, RIP 등)의 값을 보여줍니다.
•
활용: 최적화된 릴리스 모드 디버깅이나, 어셈블리 레벨에서 비트 연산 결과가 CPU에 어떻게 반영되는지 확인할 때 사용합니다.
C. 디스어셈블리 (Disassembly)
•
단축키: Alt + 8
•
기능: 현재 C/C++/C# 코드가 실제 기계어(어셈블리)로 어떻게 변환되었는지 보여줍니다.
요약: 비트 연산 디버깅 시나리오
1.
F9로 의심 가는 곳에 중단점을 겁니다.
2.
F5로 실행 후 중단점에서 멈춥니다.
3.
조사식(Watch) 창을 엽니다 (Ctrl+Alt+W, 1).
4.
변수명 뒤에 ,b를 붙여 이진수로 확인합니다. (예: flags,b)
5.
특정 비트가 켜졌을 때만 멈추고 싶다면, 중단점 우클릭 > 조건 > (flags & 0x10) != 0을 입력합니다.
