모두의 코드
씹어먹는 C 언어 - <14. 컴퓨터의 머리로 따라가보자 - 디버깅(debugging)>
이번 강좌에서는
버그란 말의 유래
디버깅
우리는 흔히 컴퓨터에 오류가 생기면 버그(bug) 가 생겼다고 합니다. 그런데 왜 하필이면 버그 일까요?
곤충? 곤충이 뭐 어째서 말이지요. 사실 이 말이 나온 계기는 먼 옛날 1940 년대로 돌아갑니다. 유명한 여자 컴퓨터 과학자였던 그레이스 호퍼(Grace Hopper) 는 하버드 대학교의 Mark II 컴퓨터를 작동시키던 중 연산에 문제가 생기는 바람에 원인을 분석하다가 컴퓨터에 나방이 들어가 일으켰다는 사실을 알게되었습니다.. 호퍼는 이 나방을 꺼내고는 곤충을 잡았다 해서 디버그(Debug) 했다고 기록했습니다.
이 일을 이후로 컴퓨터에 발생한 문제는 버그라고 하게 되었고, 이를 고치는 일은 디버그 라고 부르게 되었습니다. 참고적으로 이야기 하자면 기술적인 결함을 지칭하는 용어 버그는 호퍼 보다 훨씬 이전인 에디슨이 가장 먼저 사용하였습니다. 하지만 실질적으로 컴퓨터에서 버그가 사용된 것은 그레이스 호퍼가 처음이였지요.
우리는 이렇게 프로그램을 짜다 보면은 버그를 만나는 일이 종종 있습니다. 이번 강좌에서는 우리가 만든 프로그램의 버그를 찾아내는데 큰 도움을 주는 비주얼 스튜디오의 디버깅을 이용해보도록 하겠습니다. 뜬금없이 C 언어 강좌에 왜 이것을 갑자기 끼워넣었냐면 이 디버깅은 많은 C 언어 책들이 다루고 있는 내용은 아니지만 여러분이 C 프로그래밍을 배우다 보면 꼭 필요한 스킬이기 때문입니다. 적절한 디버깅을 통해서 여러분의 프로그램의 골치아픈 문제점들을 찾아낼 수 있습니다.
먼저 Visual Express 2008
을 실행하셔서 다음의 코드를 복사해 넣어 봅시다.
#include <stdio.h> int main() { char a, b, c; a = 100; b = 300; c = a + b; printf("%d + %d = %d \n", a, b, c); return 0; }
성공적으로 컴파일 하면 아래의 화면을 볼 수 있습니다.
으응? 우리는 흠칫 놀랄 수 밖에 없습니다.내가 b
에 300 이라는 값을 주었는데 위에 출력된 결과는 44 로 나왔습니다.게다가 44 는 그렇다 치고, 양수 +
양수를 했는데 음수가 나오다니요. 컴퓨터가 계산을 잘못한 것일까요? 음.. 아무리 생각해도 그럴 일은 있을 수 없겠군요. 그렇다면 우리는 여기서 두 가지 방법으로 왜 틀린 결과가 나왔는지 찾아낼 수 있습니다.
첫번째 방법은 밤새도록 머리를 쥐어 짜고 도대체 왜 저딴 결과가 나왔는지 고민하는 것입니다. 아무래도 일찍 자기 위해서는 효과적인 방법이 아니지요. 하지만 다행이도 두번째 방법이 있습니다. 바로, '컴퓨터의 관점에서 코드를 따라가 보는 것' 입니다. 말이 조금 어렵지만, 이 과정이 바로 앞서 이야기 한 '디버그' 입니다.
일단, Visual Express
에서 F10
을 눌러 봅시다.
오오. 무언가 새로운 창이 떳습니다. 일단, 메뉴바 쪽에 알 수 없는 내용들은 무시하고 중점적으로 살펴볼 것은 아래와같습니다. 붉은색 박스로 친 노란색의 화살표와,
맨 아래쪽의 '조사식' 부분을 살펴봅시다.
앞에서도 말했듯이 우리가 디버깅을 하는 이유는 버그를 찾아 내기 위해서입니다. 그런데, 우리가 쉽게 버그를 찾지 못하는 이유는 바로 컴퓨터가 눈 깜짝할 사이에 명령을 다 실행해 버리기 때문이죠. 만일 우리가 컴퓨터가 수를 더하고 출력하는 과정을 천천히 눈으로 볼 수 있다고 치면, 굳이 버그를 쉽게 찾을 수 있습니다. 디버깅을 하면 사용자로 하여금 각 문장이 실행되는 과정을 천천히 살펴 볼 수 있게 해서 어느 문장에서 문제가 발생하는지 알 수 있게 해줍니다. 즉, 우리가 프로그램을 실행해 버리면 컴퓨터는 문장을 순식간에 다 실행해 버리지만 디버깅을 통해 사용자가 순차적으로 문장을 하나씩 하나씩 실행할 수 있게 해주는 것입니다.
위 말이 이해가 잘 안되도 직접 해보면 쉽게 느낄 수 있을 것입니다.
먼저, 노란색 화살표 부터 살펴봅시다. 이는 '내가 다음에 실행한 코드' 를 가리키는 역할을 합니다.
아래 조사식은 내가 값을 보고 싶은 식을 써 넣으면 됩니다. 예를 들어서 내가 변수 a
의 값을 보고 싶다면 a
를 치고, a + b
의 값을 보고싶다면 a + b
의 값을 치면 됩니다. 이 디버깅 과정에서 문제가 생기는 것은 b, c
이므로, 일단 변수 a,b,c
의 값들이 어떻게 변화하는지 살펴보도록 합시다.
위와 같이 a,b,c
를 차례로 입력합니다. 어랏. 이상합니다. 변수 a,b,c
의 값이 출력되고 있지 않습니다. 왜 그럴까요? 사실, 당연한 일이지요. 노란색 화살표를 보면 현재 {
를 가리키고 있었습니다. 다시 말해 다음에 실행할 문장이 {
이므로 char a,b,c
는 실행 조차 되지 않았기 때문이죠. 따라서 컴퓨터는 a,b,c
라는 변수가 정의되어 있는지 모르기 때문에 위와 같이 a,b,c
라는 변수가 없다는 오류를 내게 됩니다.
그 다음 문장을 실행하기 위해서는 F10
을 누르면 됩니다.
어랏. 분명히 그 다음 문장을 실행한다고 그랬는데 두 줄이나 내려왔습니다. 이는 사실, 컴퓨터에서 사용자의 편의를 위해 변수를 정의하는 부분은 일일이 귀찮게 F10
을 누르지 않도록 자동으로 실행해 준 것입니다. 아무튼. 크게 중요한 부분은 아닙니다. 다음 문장을 실행하기 전에, 조사식이 어떻게 되었는지 봅시다.
모두 -52 라는 값을 갖고 있는 것처럼 보입니다. 사실, 그렇지 않습니다. 우리가 a,b,c
에 아직 아무런 값을 대입하지 않았기 때문에 현재 쓰레기 값으로 초기화 된 것입니다. 즉, -52 라는 것은 아무런 의미가 없습니다. 단순히 a,b,c
에 아무런 값도 대입되지 않았음을 나타냅니다.
이제, F10
을 또 한번 눌러봅시다. 화살표가 b=300; 을 가리켰으므로, 그 위의 문장, 즉 a = 100;
이란 문장을 실행했다는 것입니다. 따라서, 조사식을 보면,
위와 같이 a
의 값이 100 이라고 나옵니다. 이 때 옆의 'd' 는 100 에 해당하는 아스키 문자(기억 하시죠? 모르면 5강 참조) 을 나타낸 것으로, 사용자의 편의를 위해 컴퓨터가 나타내주었습니다.
마찬가지로 F10
을 눌러서 b
의 값도 정의해줍시다.
허걱. 분명히 b = 300
을 했는데 b
에는 44 가 들어갔습니다. 무언가 문제가 있어 보입니다. 사실, 이쯤 되면 무엇이 문제인지 짐작할 수 있겠지만, 아래에서 설명하도록 하죠. 마찬가지로 F10
을 또 한번 눌러서 c = a + b;
를 실행해 보면 아래와 같습니다.
조사식을 살펴 보면
c
의 값이 -112 로 되었음을 볼 수 있습니다. 또한, -112 에 해당하는 아스키문자가 ?
여서 '?' 로 출력된 것이 아니라 아스키 표에 해당하지 않는 수이기 때문에 알 수 없음의 의미로 ?
가 출력된 것입니다. 음. c = a + b;
를 했는데 왜 c
에 -112 가 들어갔을까요? 사실, 여러분이 다 짐작하고 있겠지만 이유는 간단합니다. char
의 범위가 128 까지 이기 때문이죠. 즉, b
값에 44 가 들어간 것도, 100 + 44
를 했는데 -112 가 출력된 것도 모두 char
의 범위가 128 까지 이기 때문에 발생한 일들입니다.
만일 우리가 디버깅을 하지 않았다고 칩시다. 과연 우리는 char
의 범위 때문에 그렇다라는 것을 알 수 있었을까요? 물론, 위 예제에선 그렇습니다. 예제가 간단하기 때문이죠. 우리는 손쉽게 내가 char
형의 범위를 무시하고 값을 대입해서 오류가 떴구나 라는 사실을 알 수 있습니다. 그러나, 실제 예제는 이와 같이 단순하지 않습니다. 위는 그냥 설명하기 편하게 하기 위해 위와 같이 예를 잡은 것이고, 실제 우리가 만들게 될 프로그램은 이것보다 100 배는 더 복잡합니다.
예를 들어 아래의 코드를 봅시다(사실 아래 것도 그리 복잡한 것은 아니지만 적절한 예제가 없어서.. 여러분이 직접 프로그래밍 하시다 보면 알게 될것입니다) .
/* 샘플 코드 */ #include <stdio.h> int main() { int arr[10]; int i; for (i = 0; i < 10; i++) { scanf("%d", &arr[i]); } for (i = 0; i <= 10; i++) { printf("%d \n", arr[i]); } return 0; }
성공적으로 컴파일 해보면 아래와 같이 맨 아래에 이상한 값이 출력됨을 볼 수 있습니다.
도대체 -858993460 은 어디서 나온 것일까요? 한 번 여러분이 디버깅을 통해 코드의 어느 부분이 잘못되었는지 찾아서 수정해보세요 :)
댓글을 불러오는 중입니다..