남의 집 땅은 밟지 마세요.
안드로메다마을 2008/03/01 00:40이 글의 주제는 참으로 기본적이고도 중요하고 어려운, 내 8년 코딩 인생 "디버깅 쌈질 로그"의 78.675%를 차지하는 memory access violation이다.
포인터를 몇번 써본 개발자라면 척하고 다들 아는, 예를 들면 이런 슬픈 이야기이다.
---
안드로메다 마을에 사는 순이는 C언어로 된 동물의 숲 소스를 만지작 하고 있었습니다.
인사말을 여러개 정해서 하나씩 써먹고 싶어서, 인사를 하는 부분을 살짝 고쳤지요.
다음과 같이 포인터를 선언하고 인사말을 여러 개 채웠답니다.
char** hi;
hi[0]="안녕하세요?";
hi[1]="왓썹맨~";
hi[2]="이 폐인아!!!";
hi[3]="공부나 하시지?";
print_hello_message(hi[random()]);
맨날 "안녕하세요?"만 하다가 다양한 레파토리를 확보한 순이는 신이 났어요.
컴파일 해서 다시 마을 문을 열고, 들어가 마구마구 휘젓고 다니기 시작했습니다. 패트라한테도 인사하고, 럭키한테도 인사하고, 못생긴 짠돌 너굴이한테 인사할 때마다 매번 다른 말을 할수 있는거에요!! 킹왕짱!.
드디어 이 마을에서 가장 동숲폐인부자인 룬님이 멀리서 오고 계세요. 어서 인사를 해서 잘보여야 돈을 주겠지요?
인사하자 고고!! 무브무브!!
하고 룬님을 향해 한발짝 발걸음을 옮기는 순간.
눈 앞에 빨간게 번쩍.
마을에 핵폭탄이 터져 안드로메다 마을 사람들은 모두 죽고 말았답니다.
빵!!!
(끛)
---
- 안드로메다 마을은 왜 멸망했을까?
이야기에 나오는 코드를 뚫어져라 보면 답이 나온다(...).
알고 보면 굉장히 단순한 문제이면서, 늘 실수를 하게 되는 부분이다. 메모리 할당을 잊어버리는 경우 뿐만이 아니라, 보통 다음과 같은 아찔한 일들을 많이 저지른다.
- 10개 원소를 가지는 배열이라고 해놓고 11번째 원소에다가 뭘 쓰셈! 이라고 한다.
- 할당하지 않은 메모리 영역을 free하라고 시킨다.
- 포인터 변수에 접근하다가 기존에 할당해 놓은 전역 변수의 주소값을 마구 침공한다.
- define된 상수값을 바꾸려고 시도한다.
- 시한폭탄의 무서움
리눅스나 윈도우나, 어느 운영체제에서든, 경험적으로 저런 나쁜짓을 한 경우 100% 확실히 그 시점에 "빵!!"이라고 알려주지는 못한다. 심지어 운이 좋은 경우 죽을 때까지 이게 나쁜짓을 한 거였다는 걸 모르고 지나갈 수도 있다. 이 경우보다 조금 더 운이 좋은 경우는 특정 상황에서 "빵!!"이라고 터지는 것이 반복되는 경우. 이 경우 이 상황에서부터 짚어나가면 문제가 어디 있는지 언젠가는(...) 알아낼 수 있다.
위의 순이의 경우는 가장 비참하고도 어려운 케이스.
분명히 나쁜 애는 인삿말 루틴인데, 걸어갈 때 마을이 멸망했다. 그것도 그 전에 막 돌아다닐 땐 괜찮았는데!.
나쁜 짓을 저지른 부분과 아무 상관없는 동작에서 랜덤하게 "빵!!"이 터지는 것이다.
- 어떻게 고쳐!!!
디버깅도 참 비참해진다.
필자는 보통 다음과 같은 방법을 쓴다. 그러나 이것도 머신에 따라, OS에 따라, 디버깅 쌈질을 하는 시각에 따라 메모리가 할당되는 위치가 변경되면 대략 난감해지는 것이긴 하다ㅠㅠ.
- 줄주리타 도와주세요 ㅠㅠ.
코드 검토 헬프를 요청할 추가 뇌를 확보하여 옆에 앉혀놓고 확인을 받는다. - 디버거 신공
gdb(임베디드 환경에서는 armsd같은 임베디드 컴파일러)로 각종 변수들의 16진수 주소값ㅡㅡ들을 마구 추적하여 메모리 값들중 어떤 값이 언제 별나라로 가버리는지 알아내는 방법을 쓴다. - 디버거가 없으면!
그저 하염없이 "이 코드가 맞는걸까!!"를 외치며 해결될 때까지 머리를 쥐어 뜯거나 printf 신공을 쓴다(일반론이지요). - 애초에 이런 재앙이 일어나기 전에 되도록 많은 머신, 다양한 OS환경에서 실험하여 폭탄 탐지율을 높인다(보통 사실상 힘든 힘든 경우가 많지만 가능하면..쩝).
- 줄주리타 도와주세요 ㅠㅠ.
임베디드에선- 볼사람만 보세용
지금은 디버깅 쌈질 로그가 뇌에 8년어치 쌓여있는 상태라, 대략 이런 경우의 50.32% 정도는 대충 이러이러하겠네라고 금방 찾아나갈 수 있지만, 위의 순이 이야기에 나오는 것 같은 랜덤 폭탄은 여전히 무서운 이야기이다. 한번 멸망한 마을은 이전으로 돌아갈 수 없다(...).
이 폭탄들을 어떻게 하면 개발자들이 쉽게 찾아내고 안전하게 제거할 수 있을까 하는 문제는 고민해 볼만 한 것 같다.
메모리 공간을 꼼꼼하게 체크하는 메커니즘을 디버거에서만 고안해도 선량한 프로그래머의 철야 질주가 좀 덜하지 않을까나.
그러나 완벽하지 않은 데는 다 나름의 이유들이 있는 걸 알기에 ㅠㅠ.
OS나 컴파일러가 이래서 외계분야인 거지.
"남의 집 땅은 밟지 마세요" 라는 팻말보다는,
남의 집 땅을 밟는 순간 삐요삐요가 울리며 "꼼짝마"를 외치는 코딩 사회를 난 원한다고!!!.
ps: 한참 신나게 포스팅을 하다가 컴퓨터씨가 다운되는 바람에 다 날리고(쉤),
의욕이 30%로 줄어 내용의 의도와 성실함도 30%로 줄었다.ㅡㅡ;;
