미니덤프를 사용하자!!
이번엔 진짜다. 미니덤프를 꼭 사용하자!
대부분의 어드밴스드 프로그래머(advanced programmer)-_-들은 프로그램의 비정상 행동에 대처하기 위해 콜스택(callstack)을 캡쳐하여 버그(Bug)를 잡을 것이다. 비정상 종료됐을때 콘솔이나 파일에 기록된 콜스택과 레지스터(register)의 정보를 토대로 디버깅하는 방법에 대한 테크닉들은 널리 퍼지고 잘 알려져있다. MSDN의 Bugslayer나 codeguru, codeproject 혹은 google에서 callstack으로 검색하면 산더미 만큼 나올 것이다. 이 콜스택에 대한 정보를 이용하면 일반적인 대부분의 비정상 종료를 대해 잡을 수 있다. assert를 이용해서 단순히 소스파일이름과, 줄번호만 가지고 잡던 시절에 비하면 이 것만으로도 디버깅을 위한 축복이다.
이 포스팅의 주인공 미니덤프(Minidump)는 디버깅을 수월하게 하기위해, windows xp 이후에 등장하였다. (엄밀히 말하면 2k와 xp사이에 ms가 내부에서 디버깅에 사용하던 것을 공개한듯 하다.) 2k를 포함한 이전의 윈도우즈에서 이를 사용하려면 최신버전의 dbghelp를 사용하면 된다. 미니덤프는 실제로 비정상 종료가 일어났을때의 일부 메모리에 대한 덤프를 저장하는 것이다. 여기에는 대부분의 쓰레드 정보, 각 쓰레드의 콜스택정보를 포함한다. 사실 일반 프로그램이라면 미니덤프까지도 필요 없고 비정상 종료가 발생한 콜스택만 가지고도 대부분의 디버깅이 가능하다. 하지만, 멀티쓰레디드 프로그램에서라면 상황은 달라진다. 프로그램이 그냥 죽어버리면 다행이겠지만, 프로그램은 죽지 않았는데 쓰레드끼리의 동기화 문제로 정상적으로 프로그램이 동작하지 않는 상황이 발생하는 것이다. 이에 스타베이션(굶주림,starvasion)이나 데드락(deadlock) 문제가 포함된다.
미니덤프가 평소에 별 도움을 주지 않아서 덤프만 남기고 잘 살펴보지 않으며 등한시 하였는데, 오늘 한달간 나를 괴롭히던 '데드락'을 미니덤프를 이용하여 잡았다. 마왕을 물리쳤다! -_-
최근의 업계 동향으로 따진다면, 쓰레드끼리 동기화를 해야하는 멀티쓰레디드 프로그래밍 패러다임 자체에 대한 회의가 짙은듯하다. 최근이라고 하기도 뭐하고 꽤나 오래전부터 이 '능률적인' 멀티쓰레디드 프로그램을 만드는 것은 어렵다고 알려져있다. 사실 멀티쓰레디드 프로그래밍은 조낸 쉽다. 그냥 동기화 객체를 쳐 발르면 성능하고는 관계없이 정상적인 동작을 수행한다. 하지만 '능률적인' 멀티쓰레디드 프로그램은 확실히 어렵다. (이러한 추세를 반영하는 것으로써 OpenMP가 있다. VS.Net 2k5에 포함되는걸로 알고있다.)
이것과 관계된 약간의 팁이라면, win32 structured exceptional handling을 이용하여, 아무때나 특정한 순간에 callstack과 minimap을 찍는 것이 가능하다. 그냥 잘못된 연산을 수행하고 recovery하면 된다. 자세한 문법은 msdn에 잘 나와있을 것이다. 위의 '마왕'은 데드락에 걸렸다고 판단이 났을때에, 미니덤프를 뜨고 그 미니덤프를 이용하여 각 쓰레드의 상태를 살펴보니 전부 락을 거는 소스코드위치에 쓰레드가 대기하고 있는 것을 보고 발견하였다. 다들 젓가락 한개씩 들고 있었다. -_-
fin.
