Company
교육 철학

Visual Studio 디버깅 마스터 가이드

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
-
메모리 뷰 확인
문자열 포인터 등의 메모리 덤프 확인
Tip: C++에서는 변수명,bb를 입력하면 앞의 0b를 뺀 순수 비트값만 볼 수 있습니다.

B. 의사 변수 (Pseudo-variables)

디버거가 제공하는 특수 변수로, 현재 상태를 추적할 때 유용합니다.
$err (또는 $hr): 마지막으로 발생한 오류 코드(GetLastError 값)를 보여줍니다. API 호출 실패 원인을 찾을 때 유용합니다.
$returnValue: 방금 실행된 함수의 반환값을 보여줍니다. (변수에 받지 않고 실행만 했을 때 확인 용도)
$exception: (C#) 현재 발생한 예외 객체의 정보를 보여줍니다. catch 블록 내부에서 유용합니다.

3. 스마트 중단점 (Advanced Breakpoints)

단순히 멈추는 것이 아니라, 조건이나 로깅을 위해 사용합니다. (빨간 점 우클릭 \rightarrow 조건/작업)
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를 우클릭 \rightarrow 동결(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을 입력합니다.