부산에서 대학을 졸업하고 처음 회사에 입사했을 때, 회사의 프로그램이 시연도중 갑자기 죽어버린 경우가 있었습니다.

시연 처음부터 잘 되던게 어느 시점부터 갑자기 프로그램 화면이 깨어지면서 죽어버리는 것이었죠.

실제 개발을 하던 사람들은 막상 벌어지는 상황에 이것 저것 머릿속으로 확인을 하고 있는지라 쉽게 원인을 알 수 없게 됩니다.

사실 제가 갔을 때는 이미 릴리즈 전 단계여서 제가 참여한 부분이 크지 않아 저는 마음편히 왜 그럴까 하고 생각을 했었습니다.

그러다가 결국 판단 내린 것이 프로그램이 깨어진 걸로 보아 GUI 모듈이다 라고 잠정적인 결론을 내고 GDI 개체 수를 확인한번 해보고 싶다고 말씀드렸습니다.

아니나 다를까 해당 프로그램의 GDI 개체수가 10,000 개 였습니다. 그래서 부랴 부랴 담당 개발자 분들은 GDI 개체 반환 코드를 삽입했습니다.

그 뒤로는 갑자기 죽어버리는 경우는 발생하지 않았습니다. ^^;

이번에 확인해볼 부분도 GUI 프로그램의 GDI 개체 관리에 관한 것입니다.

일반적으로 GDI 개체가 풀이되서 프로그램이 튕길 경우 아래와 같이 그 여부를 확인 할 수 없게 나타납니다.

사용자 삽입 이미지


그럼 문제가 되는 코드를 한번 살펴 보겠습니다.
CDC MemDC, *pDC;
pDC = GetDC();
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp, bmp;
bmp.CreateCompatibleBitmap(pDC, m_dwMaxX, m_dwMaxY);
pOldBmp = (CBitmap*) MemDC.SelectObject(&bmp);

Draw(&MemDC); // 멤디시 작업

pDC->BitBlt(0, 0, m_dwMaxX, m_dwMaxY, 
              &MemDC, 0, 0, SRCCOPY);
MemDC.SelectObject(pOldBmp);
MemDC.DeleteDC();
bmp.DeleteObject();
보통 위와 같이 작성을 하게 됩니다.
dc 작업은 알고리즘 모듈이 아니기 때문에 빠르게 작성하게 되는 것이 사실입니다.
하지만 위와 같이 작업을 마무리 할 경우 아래 그림과 같이 GDI 개체가 엄청 증가하게 됩니다.

사용자 삽입 이미지


그리고 아래 그림과 같이 GDI 개체가 만개로 풀이 되고 프로그램은 퍽~ 하고 죽어버립니다.

사용자 삽입 이미지


사용자 삽입 이미지


그럼 위의 코드에서 GDI 개체가 증가하게 된 원인이 되는 코드와 개체 증가와 감소가 어떤 코드에서 발생하는지 정확하게 한번 확인해 보죠.



위의 코드와 같이 마지막에 애초에 획득한 pDC의 핸들에 대한 포인터에 대해 풀어주지 않아 문제가 생긴 것업니다.

MSDN 에서도 CWnd::GetDC() 를 사용할 경우 CWnd::ReleaseDC()를 호출해야 함을 명시하고 있습니다.

간단하게 확인했습니다만, GUI 프로그램 테스트를 하면서 GDI 개체가 풀이 될 경우는 잘 없기 때문에 프로젝트를 수행하면서 종종 확인을 하지 않게되는 경향이 있습니다.

하지만 프로그램이 중간에 엔드유저가 원인 모를 이유로 종종 죽어버린다면 해당 프로그램과 그 개발자에 대한 신뢰도가 무척이나 무너질 여지가 다분합니다.

따라서 프로젝트의 테스트중에는 꼭 GDI 개체 관리에 관한 테스트도 함께 해야 할 듯합니다. 콘솔일 경우는 맘 편하게 안해도 되겠지만요 ^^

사용자 삽입 이미지

Timer.exe


이번 포스팅에 제물이 된 프로그램은 일반적으로 프리젠테이션시 청중들에거 잠시 10분간 휴식의 시간을 줄 때 사용할 수 있는 "10분간 휴식!" 이란 프로그램 입니다. 실행시키면 전체화면으로 실행되며 10분의 시간이 줄어드는 것을 확인할 수 있습니다. 또한 10분이 지나면 괄호안의 초과한 시간이 증가하게 되며 중간은 0:00:000 이란 부분이 깜빡거리게 됩니다.

물론 위의 GDI 개체 반환코드는 모두 정상적으로 넣어놨기 때문에 안전하게 사용할 수 있습니다.

실행시 아규먼트로 분단위의 입력을 하면 10분이 아닌 다른 시간으로 설정이 가능합니다.


P.S. 서울 날씨 무척이나 구리네요 -_ㅡ; 얄굿은 먹거리 사서 집에가서 공포영화나 봐야겠습니다. ^-^
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기