본문 바로가기

카테고리 없음

C++ GDI 생성자 Crash/Dead

SMALL

포스팅 계기

 최근에 SW Release가 얼마 남지 않아 바쁜 일상을 보내고 있었다. 그러던 중 원인을 알 수 없는 Crash가 일정 시간이 지난 후 발생하여 근 몇 달 동안 해결하지 못하고 있었다. 최근에 해당 문제를 해결하게 되어 나와 같은 이슈를 겪고 있는 개발자들에게 도움이 되었으면 하는 바람에 글을 쓰게 되었다. 
 


GDI 생성자 Crash

 계속 죽는 곳은 GDI 객체를 생성하는 곳에서 죽었다. 코드를 보니 큰 문제가 없고, 해당 코드는 매 1초마다 호출되는 로직이기에 죽는다면 진작 죽어야 한다고 판단했다. 그래서 나는 다양한 접근 방법으로 문제를 해결하기 위해 노력했고, 아래에는 내가 죽는 문제를 해결하기 위해 접근했던 방법을 정리해 봤다.

✅ 1) 죽은 지점 Code 의심

→ 다이얼로그에서 그림을 그리기 위해 GDI 객체를 생성하는 로직으로 GDI tempGDI(this)와 같은 코드로 크게 문제가 될 건 없다고 판단하였다.
 

✅ 2) 전/후 로직 Code Review

→ 호출스택을 통해 전후 3 Death까지는 코드를 모두 리뷰하였지만, Memory Corruption이 발생할 것 같은 로직은 전혀 없었다.
 

 3) 다양하게 죽는 시점의 공통점 

→ 약 10번 정도의 죽은 시점의 공통점을 모두 정리하였는데, 공통점은 단 하나였다. Test Condition에 따라 다르지만, 약 2시간 정도 뒤에 SW가 죽는다는 것이다. 다만 해당 공통점은 나에게 큰 Hint는 아니었다. 그래서 해당 부분을 무시하고 1번 2번을 무한 반복하다가 혹시 몰라 작업 관리자에서 GDI 개체 수를 Check 하였는데, 아무 동작을 하지 않아도 계속 늘어나고 있었다. 추가로 사용자가 프로그램을 사용하면서 다이얼로그를 많이 사용할수록 더 빨리 증가하였다. 평균적으로 우리 PC에서 사용할 수 있는 GDI의 개수는 65535(2^16 - 1)이다... 그렇게 쭉 프로그램을 실행하면서 지켜보니 65535가 될 시점에 죽었다... 기분이 좋으면서도 바보 같다는 생각을 잠시 했다. 하지만 여기서 누수를 어떻게 다 찾을 것인지가 중요하다. 해당 방법은 아래에서 소개하겠다.


GDI 개체 수 작업 관리자에서 확인하는 방법

1. 작업 관리자에서 자세히 버튼 선택하기

 
2. GDI 개체수 확인을 위해 열 선택하기
  - 이름 열 위에 오른쪽 마우스 버튼으로 메뉴 전시에 열 선택 메뉴 선택

 
3. GDI 열 추가하기
   - GDI 개체 선택 후 확인 버튼 누르기

 
4. GDI 개체 수 확인

 


GDI 개체 수 누수 지점 찾는 방법

 
🔍 내가 사용한 방법은 검색을 하다 보니 Deleaker라는 누수 지점을 확인시켜주는 프로그램이 있었다. 아래 링크에 접속하면 14일 체험판을 사용할 수 있다.
https://www.deleaker.com/download.html

Get Deleaker Trial

Buy Deleaker Deleaker is compatible with Visual C++ 6.0, Visual Studio 2005, 2008, 2010, 2012, 2013, 2015, 2017, 2019 and 2022, Delphi / C++ Builder / RAD Studio, and Qt Creator. Deleaker supports all major compilers including the Microsoft Visual C++ comp

www.deleaker.com

 
🔍 해당 프로그램을 설치하게 되면 아래와 같이 확장 메뉴에 Deleaker 프로그램이 추가되어 있는 것을 확인할 수 있다.

🔍 해당 프로그램이 설치된 것을 확인하게 되면 Deleaker에 Enable Deleaker 선택하게 되면 아래와 같이 Disable Delaker로 변경이 되면서 활성화가 되고 Deleaker 실행 후 사진과 같이 해당 UI가 전시되게 된다. 

Deleaker 실행 후

🔍 전시된 상태에서 프로그램을 실행하게 되면 아래와 같이 어떤 걸 분석할 것인지 Check 할 수 있게 나오고 나는 필요한 GDI objects만 선택하였다. 나도 누군가의 방법을 보고 한 것이 아니라 그냥 막 누르면서 한 거라 정확하지 않을 수 있다.

 
🔍 Take Snapshot 버튼을 누르게 아래에 모자이크 처리된 구간에 상세한 지점이 다 나오게 된다. 추가로 SnapShot을 여러 개 찍은 후 Diff도 볼 수 있으니 특정 시점에 보고 싶으면 해당 기능을 활용해도 좋을 것 같다.


🎯 포스팅 마무리

 최근에 겪은 문제 중에 가장 찾기 힘들었는데, 나와 같은 상황을 겪고 있는 개발자가 있다면 도움이 되기를 바란다.