음.. 오늘 GDI+ 에서 memory leak 이 발생할 경우 비주얼스튜디오가 전혀 감지를 못하는걸 보고 미친듯이 뷁뷁을 외쳐주다가 찾은자료.
http://www.codeproject.com/vcpp/gdiplus/gdiplush.asp
일단 읽어보니 GDI+ 의 경우 자체적인 메모리 할당 연산자를 사용하는데 이것이 Gdiplus.dll 내부에서 어찌어찌 쌓여서.. 비주얼 스튜디오에서는 감지를 못하는 상황인듯 하다.
위에서 사용한 방법은 특정 메크로가 정의 되어있지 않을때(!)는 GdiplusBase 객체를 자체적으로 다시 정의해서 내부의 메모리 할당 연산을 일반적인 new/delete (윈도우에서 가장 기본적으로 제공함으로써 비주얼스튜디오에서 감지가능한것)을 사용하게 하는것이다.
위의 URL에서 다운을 받으면 헤더 파일이 나오는데 그걸 Gdiplus.h 대신 인클루드 하고 사용하면 된다.
MFC에서 new 를 DEBUG_NEW로 재정의 하는 것과 비슷한… 거시기.
아래는 위의 URL의 소스를 기억용으로 한글로 주석 달아놓은것
아직 깔끔하게 적용하지 못해서 좀 찝찝하다.
예를 들어 메모리 릭이 났을 경우 소스파일의 라인을 출력해야 되는데 이건 그냥 저 헤더파일을 출력한다. 메크로로 잘 정의하면 될것 같긴 한데 느므느므 귀찮다.
GeSHi © 2004, Nigel McNie
#ifndef _GDIPLUSH_H_INCLUDED_
#define _GDIPLUSH_H_INCLUDED_
/// @file AntGdiplusHelper.h
/// @brief GDI+ 메모리 연산자 재정의 헤더파일. 메모리 누수시 감지를 위함.
/// @warning Gdiplus.h 대신 해당 파일을 인클루드 해야 함.
/// @warning Debug 에서는 GDIPLUS_USE_GDIPLUS_MEM 정의 하지 않음 -> Gdiplus 메모리 연산자를 사용하지 않고 릭 감지 가능
/// @warning Release 에서는 GDIPLUS_USE_GDIPLUS_MEM를 정의함 -> Gdiplus 메모리 연산자를 사용하지 않고 릭 감지 못함
//
// GDI+ helper file v1.0
// Written by Zoltan Csizmadia (zoltan_csizmadia@yahoo.com)
//
// GDIPLUS_USE_GDIPLUS_MEM:
// 위의 메크로가 정의 되어있을때 GDI+ 에서 제공하는 메모리 할당 함수를 사용한다.
// 이 경우 _CrtXXXXX에 해당하는 메모리 디버깅용 함수가 일반적으로 작동하지 않는다.
// (원래 GDI+는 _CrtXXXX 가 작동하지 못했다. 즉 해당 메크로를 설정하는게 기본설정.)
//#define GDIPLUS_USE_GDIPLUS_MEM
#ifdef _GDIPLUS_H
#error Gdiplus.h is already included. You have to include this file instead.
#endif
#define _GDIPLUSBASE_H
namespace Gdiplus
{
namespace DllExports
{
#include “GdiplusMem.h”
};
class GdiplusBase
{
public:
#ifdef _DEBUG
static void* __cdecl GdiplusAlloc( size_t nSize, LPCSTR szFileName, int nLine )
{
#ifdef GDIPLUS_USE_GDIPLUS_MEM
UNREFERENCED_PARAMETER(szFileName);
UNREFERENCED_PARAMETER(nLine);
return DllExports::GdipAlloc(nSize);
#else
return ::operator new( nSize, szFileName, nLine );
#endif // GDIPLUS_USE_GDIPLUS_MEM
}
static void GdiplusFree( void* pVoid, LPCSTR szFileName, int nLine )
{
#ifdef GDIPLUS_USE_GDIPLUS_MEM
UNREFERENCED_PARAMETER(szFileName);
UNREFERENCED_PARAMETER(nLine);
DllExports::GdipFree(pVoid);
#else
::operator delete( pVoid, szFileName, nLine );
#endif // GDIPLUS_USE_GDIPLUS_MEM
}
void* (operator new)(size_t nSize)
{
return GdiplusAlloc( nSize, __FILE__, __LINE__ );
}
void* (operator new[])(size_t nSize)
{
return GdiplusAlloc( nSize, __FILE__, __LINE__ );
}
void * (operator new)(size_t nSize, LPCSTR lpszFileName, int nLine)
{
return GdiplusAlloc( nSize, lpszFileName, nLine );
}
void (operator delete)(void* pVoid)
{
GdiplusFree( pVoid, __FILE__, __LINE__ );
}
void (operator delete[])(void* pVoid)
{
GdiplusFree( pVoid, __FILE__, __LINE__ );
}
void operator delete(void* pVoid, LPCSTR lpszFileName, int nLine)
{
GdiplusFree( pVoid, lpszFileName, nLine);
}
#else // _DEBUG
static void* __cdecl GdiplusAlloc( size_t nSize )
{
#ifdef GDIPLUS_USE_GDIPLUS_MEM
return DllExports::GdipAlloc(nSize);
#else
return ::operator new(nSize);
#endif // GDIPLUS_USE_GDIPLUS_MEM
}
static void GdiplusFree( void* pVoid )
{
#ifdef GDIPLUS_USE_GDIPLUS_MEM
DllExports::GdipFree(pVoid);
#else
::operator delete( pVoid );
#endif // GDIPLUS_USE_GDIPLUS_MEM
}
void* (operator new)(size_t nSize)
{
return GdiplusAlloc( nSize );
}
void* (operator new[])(size_t nSize)
{
return GdiplusAlloc( nSize );
}
void (operator delete)(void* pVoid)
{
GdiplusFree( pVoid );
}
void (operator delete[])(void* pVoid)
{
GdiplusFree( pVoid );
}
#endif // _DEBUG
};
};
#include <Gdiplus.h>
#endif
Parsed in 0.179 seconds
GDI+에서 그런식으로 메모리를 처리한 이유가 있을테니… 디버깅시가 아닐 때에는 원래 메모리 연산자를 써야하고…
크아 이 설정은 요렇게 저 설정은 저렇게 하다가 에러나기 시작하면 초난감인데! ㅂ뤡ㄹ부레게뷁
저 위의 헤더파일 추가하고
#define new DEBUG_NEW
도 정의 해놓으니깐 걍 잘되내 -_-;
릭난곳 소스코드랑 라인도 나오고.
당췌 어떻게 변환하는건지 이해가 안가는데!