본문 바로가기
Engineering/C/C++

삽질을 하다가...

by Humaneer 2009. 8. 16.


디버깅이 어려운 이유는 간단하다.

사람들은 자기가 보고자 하는 것만 보기때문이다. 아는 것만 보려하기 때문이다. 코드의 에러를 예측할 때는 자기가 아는 만큼 안에서 예측을 하게 된다. 고로 경험과 지식, 그리고 이 것들을 지혜로 흡수한 사람은 당연히 디버깅을 잘한다.

결론 : 무식이 죄다. ㅋ



어제 런타임 에러가 난 버그가 포함된 코드이다. 분명히 delete [] buf;  이 구문에서 런타임 오류가 나는 걸 바로 잡아냈다. 처음엔 후~ 뻔하지 동적으로 할당한 메모리를 초과해서 내가 무슨 짓을 하였구나~. 그런데 난 절대로 14바이트 이상 초과하여 무슨 짓을 하지 않았다. 그런데 이놈의 코드가 계속 런타임 에러를 내는 것이었다. 20분 정도를 들여다 본 후에야 나는 어디가 문제인지 그제야 알아차렸다. 후 -_-

대부분 C/C++를 배운 사람들은 위의 코드를 보자마자 어디가 잘못되었는지 바로 알 것이다. 심지어 10분전에 new연산자에 대해 배운 C++ 초봉들도 어라 저거 맞는 코드인가? 라고 생각할 것이다. 

   1. BYTE* buf = new BYTE(14);
   2. BYTE* buf = new BYTE[14];

그렇다. [] 대신에 ()를 써서 생긴 런.타.임(run-time) 오류이다. 컴파일 과정에서 전혀 무리가 없는 코드이다. 처음에 저 버그를 발견하고 나서 아니 이놈의 컴파일러가 왜 에러를 안내지? 라고 생각하며 컴파일러에게 분풀이를 하였다.  하지만 조금만 생각을 해봐도 "에러를 낼 수가 없군~" 이라는 결론이 난다. 당연한거지만 바로 생성자 때문이다.

즉 컴파일러는 1번 코드에는 BYTE만큼의 크기(1바이트)로 동적으로 메모리를 할당한 다음, ()을 보고 아~ 생성자를 호출하여야 겠군! 이러면서 1바이트의 메모리에 14라는 값을 넣어주고 그 주소값을 buf에 저장하였다. 2번 코드는 []를 보고 14바이트 만큼 동적으로 메모리를 할당하고, 첫번째 주소를 buf에 저장한 것이다.

1번 코드에서는 동적으로 할당된 메모리는 1바이트인데, 14바이트인줄 알고 이것저것 해댔으니 당연히 delete 할 때 에러가 날 수 밖에 ... 그런데 BYTE라고 해봐야 unsigned char인데 저건 분명히 C/C++의 기본 자료형이다. int, char 같은 놈들에게도 생성자가 있단 말인가? 테스트를 해보았다.

int a(5);   과연 이 코드가 C 컴파일러는 어떻게  처리하고, C++에서는 어떻게 처리할 것인가?

C와 C++ 컴파일러는 과연 어떻게 처리할 것인가. 얼마전에 소개한 http://www.codepad.org 에서 코드를 돌려보았다. 역시나~ 결과는 예상대로 나왔다. 링크를 따라가보면 C컴파일러는 에러를 내고,  C++ 컴파일러는 정상적으로 컴파일을 하고 실행하여 5라는 결과를 보여준다.

C 코드 : http://codepad.org/g0nB7w2B
C++ 코드 : http://codepad.org/0FhQsQu2


결론 : C에 객체지향이라는 개념이 추가되면서 C++가 나왔고, 그러면서 생성자라는 개념이 생기면서 새로 생긴 문법이었다.

어처구니 없는 삽질을 하며 얻어낸 작은 지식이자 작은 재미이다. ㅎ