이번에 상당히 황당스런, 하지만 결과를 알고보니 그럴것도 같다는 문제성 코드 때문에 또 하루의 수십%에 해당하는 시간을 소비해 버렸다.
Need는 OpenGL의 텍스쳐맵핑 소스로 BMP, JPG, PNG, GIF등 다양한 이미지 포멧을 사용하기 위해 GDI+의 Bitmap 클래스를 사용하게 되었는데, 이상하게도 Bitmap 클래스를 new 연산자를 통해 Heap에 할당하고 당연이 소멸자에서 delete를 하면 메모리 충돌이 나는 것이였다. delete를 어디선가 두번해 주는 것이 아닌가 하는 의문이 들었으나 그런 부분은 없는 듯 하였다. 또한 분명히 delete 하기전에 클래스의 참조 포인터가 NULL인지를 확인하는 조건까지 따져 코딩했었고….. 오늘은 포기하고 낼 맑은 머리로 해야지 싶어 포기할때쯤, 그 원인이 잡혔다.
프로그램이 시작되면 GDI+ 초기화가 일어나고 종료되면 GDI+ 정리가 일어난다. 문제는 Bitmap 클래스의 해제가 GDI+ 정리 이후에 호출되어져 메모리 충돌이 일어나는 것이였다. 즉, GID+ 관련 클래스들의 생성과 해제는 반드시 GDI+의 초기화와 정리의 중간에 발생해야 한다는 것..! 알고보니 당연한듯도 하다.
하지만 정말 당연한 것일까? 혹시 이런 것은 아닌가..
일단 한번 GDI+ 관련 클래스가 만들어지면 GDI+는 자신의 Namespace의 클래스 중, 생성된 인스턴스를 모두 관리하고 있다는 것. .NET 프레임워크에서 GDI+는 기존의 GDI를 완전이 새롭게 대체하는 요소이다. .NET 하면 GC, 즉 가비지 컬렉션이라는 개념이 존재하는데, 개발자가 생성한 객체를 따로 delete와 같이 직접 메모리에서 해제하지 않아도 알아서 해제를 해주는 참으로 편리한 개념이다. 혹시 이러한 .NET의 중요한 일부를 차지하는 GDI+가 GC를 위해 자신의 Namespace 하의 모든 클래스의 생성을 알고 있기 때문이 아닐까?
이것이 사실이라면 GDI+의 클래스들을 생성하고 직접 해제하지 않아도 GDI+의 정리코드를 호출하면 자동으로 해제된다는 개념이다. 그런데 실제로 GDI+ 클래스를 직접 delete하지 않아도 메모리의 누수가 발견되지 않았고, GDI+를 해제하는 즉시, GDI+ 클래스의 인스턴스의 아무리 사소한 맴버변수나 함수의 호출에 실패한다. 즉, GDI+의 해제시 GDI+의 클래스들의 모든 인스턴스는 무효화 되며 자동적으로 delete 되는 것 같다. Managed가 아닌 개발 환경에서도 말이다.