디버깅 ( Debugging ) 은 무엇일까?
프로그램에서 발생하는 버그 ( 오류 ) 를 찾아내고 고치는 과정
그냥 실행하면 오류가 어디서 나는지 알기 힘들다.
작업이 오랜 기간 진행 되었을 때 오류가 발생하면
많은 줄에서 오류코드를 찾기가 매우 힘들다.
Visual Studio 에는 코드 에디더, 빌더 ( 컴파일러 ), 디버거 ( Debugger ) 가 모두 한 곳에 내장되어있다.
그러기에 통합 개발 환경 ( Integrated Development Enviroment ) 이라고 부른다.
Visual Studio 의 디버거 ( Debugger ) 기능은 프로그래밍에서 아주 중요한 도구이다.
코드 실행을 잠깐 멈추고, 내부에서 무슨 일이 일어나는지 확인할 수 있게 해주는 기능이다.
디버거가 필요한 이유
static void Main(string[] args)
{
uint increasingNum = 1;
uint endPoint = uint.MaxValue;
while (true)
{
increasingNum*=2;
Console.WriteLine(increasingNum);
if (increasingNum > endPoint)
{
Console.WriteLine($"{endPoint} 초과로 종료");
break;
}
}
}
그럴싸해 보이는 코드이다.
increasingNum 는 음수가 될 일이 없으니 uint 로 변경
이론 상으로 1이었다가 두 배씩 증가하던 도중 uint.MaxValue 즉, uint 의 최대 범위를 벗어나면
무한 반복문은 break 시키라는 코드를 짤 의도로 작성한 상황이다.
Visual Studio 상에서도 문제가 발생하지 않았다고 보고한다. (빨간 밑줄)
문제가 없길 바라며 실행을 해본 결과 0 이 무한으로 출력되는 것을 볼수 있다.
일단 문제가 발생한 콘솔창의 작업을 중단시키자.
창에서 x 를 클릭하면 콘솔창이 바로 종료되지만
콘솔창에서 Ctrl + C 를 하면 콘솔 창이 닫히지 않고 남아있어 현재까지 출력된 내용들을 확인할수 있다.
컴파일러 상에서 코드나 문법을 잘못 입력하여 문제가 생기는 것을 보고
Syntex Error 즉, 문법 오류라고 부른다.
이는 IDE의 도움을 받아 간단히 수정할 수 있지만
지금 상황처럼 개발자의 코드 작성 의도와는 다른 결과물이 나오고 있는 상황을 보고 논리 오류 ( Logic Error ) 가 났다고 한다.
어느 줄에서 문제가 발생했는지 친절히 바로 알려주는 문법 에러와는 달리
논리 오류는 컴퓨터의 입장에서 인간이 지시한 대로 올바르게 작동을 하고 있는 상황이므로
잘못 지시한 사항을 개발자가 고치는 것이 관건이다.
디버거의 주요 기능
1. 중단점 ( Breakpoint )
- 코드 특정 줄에 빨간 점을 찍어두면 프로그램 실행 중 그 줄에서 멈춘다.
- 빨간 점을 찍는 단축키는 F9
- 멈춘 상태에서 변수 값, 흐름 등을 확인할 수 있다.
2. 단계별 실행
- F10 ( Step Over ) : 현재 줄 실행 후 다음 줄로 이동 ( 함수 안은 들어가지 않는다 )
- F11 ( Step Into ) : 함수 내부로 들어가서 실행
- Shift + F11 ( Step Out ) : 함수 실행을 끝내고 빠져나온다
- 코드가 어떻게 흐르는지 한 줄씩 따라가며 확인이 가능
3. 변수 값 확인
- 실행이 멈춘 상태에서 변수에 마우스를 올리면 현재 값 확인 가능
- Watch 창이나 Locals 창에서 여러 변수 값들을 실시간으로 추적이 가능하다
4. 호출 스택 ( Call Stack )
- 현재 함수가 어떤 경로를 통해 호출되었는지 추적
5. 조건부 중단점
- 특정 조건일 때만 멈추게 설정 가능
위의 코드 에러 수정
unit 는 0 부터 4,294,967,295 까지의 숫자를 담을수 있다.
즉, int의 음수 범위를 잘라내고 양수 쪽을 두 배 확장한 자료형이 uint 이다.
곱셈을 진행하다가 uint가 표현 가능한 범위로 넘어가버려서 숫자가 의도치 않는 수를 표현하기에 에러가 난다.
계속 2를 곱해주다가 HEX ( 16진수 ) 값이 8000 이 되는 순간 10진수는 음수가 된 것을 확인할수 있다.
HEX ( Hexadecimal ) 의 줄임말
여기서 한번 더 곱셈을 진행하는 순간 10진수는 0 이 되는걸 확인할 수 있다.
F11을 눌러서 더 진행을 해보면 0 이 되어버린 수는 uint가 표현 가능한 최대수보다 클 리가 없으니
if 문을 무시하고 while 로 돌아온다. 0 곱하기 2 를 해도 계속 0 이 되니 break 문에 절대 도달하지 못한다.
그래서 0 이 무한으로 출력된다.
static void Main(string[] args)
{
uint increasingNum = 255;
uint endPoint = uint.MaxValue;
while (true)
{
if((long)increasingNum *2> uint.MaxValue)
{
break;
}
else
{
increasingNum = increasingNum * 2;
}
Console.WriteLine(increasingNum);
}
}
디버깅으로 오류를 찾아내서 수정
이번에는 문제 없이 제대로 실행되는 것을 확인할수 있다.
정리
- 디버거는 프로그램 실행을 멈추고 내부 상태를 분석할 수 있는 도구이다
- 핵심 기능 : 중단점, 단계 실행 ( F10/F11 ), 변수 확인, 호출 스택
- 버그를 고치고, 코드 동작 원리를 학습할 때에도 필수적인 기능