undefined behavior
전산
2009/06/11 01:30
C/C++ 같은 언어를 다루다 보면 아무래도 사람인 이상 메모리를 꽤나 깨먹게 된다. 표준에는 그냥 간단히 undefined behavior 라고 해서 "니가 잘못한거니까 무슨일이 일어나도 놀라지 마셈~" 정도로 다루고 있는데 이런 정의되지 않은 동작을 대했을때 프로그래머의 대응이 난 중요하다고 본다.
얼마전 키즈에 이런 질문 (#2) 이 올라왔었는데 대번에 붙는 대답이 "그건 99% 님이 메모리를 깨먹어서 그런거임." 이라던가 "부동소수점은 == 로 비교하면 안됨" 같은 대답이 달렸었다. 사실 저건 extended floating point 변환 문제였고 다른분이 http://kldp.org/node/105975 에 해답을 주셨다. (참고로 중간에 How not to program in C++(2003) 책에 소개되어 있는 문제라고 하는분이 있는데 그 책의 해당 내용은 그냥 일반적인 부동소수점 유효숫자 내용으로 본래 문제와 별 상관이 없는걸로 알고있다.)
원 질문자의 소스코드를 보고서는 저건 메모리 문제가 아니라는걸 알아챌 수 있다면 좋을 것이다. 사실 힌트는 충분히 있었다. 이미 printf() 가 앞뒤로 정상 동작했기에 스택은 최소한 수행 결과를 왜곡할 만큼 심각하게 망가지지 않았다는걸 알 수 있고, 메모리가 밀린경우 부동소수점이 0.00001 식으로 사람이 읽기 좋게 떨어지는 경우는 거의 드물기 때문이다. 그리고 단순히 메모리를 읽기만 하는 독립적인 명령어들의 순서를 바꿨는데 결과가 달라졌다면 이건 최적화등과 관계가 있다는것도 알 수 있다.
"메모리를 깨먹었겠지" 라는건 달콤한 유혹이다. 이건 '내가 모르는 모든 문제들' 에 대해 항상그럴듯한 답변이 되어줄 수 있기 때문이다. 어떤 문제가 발생했는데 인과관계를 증명하기도 전에 근처 어딘가에 숨어있던 메모리 버그를 발견하고 "이것 때문이었군!" 하고 탐색을 중단하는 프로그래머를 주변에서 많이 봤다. (사실 고백하자면 내가 그랬었다. -_-;) 물론 그것으로 해결되지 않는 문제들이 많았다.
그래서 나는 undefined behavior 가 일어났을때, 왜 그런 결과가 나왔는지 증명하는 것을 권장한다. 어떤 예외가 발생했는지, 어디의 메모리를 접근하다 문제가 터졌는지, vtbl 은 어떻게 되어 있는지, 스택과 레지스터의 상태는 어떤지 등등.. 리버서 수준까지 될 필요는 없다. 그냥 예외정보가 확실한지 증명만 하면 된다.
진짜 이렇게 까지 하면서 프로그래밍 해야되나 싶지만 C/C++ 이란게 원래 좀 그렇다. -_-








Textcube 1.8.5 : Accelerando