none MFC에서 memory leak난 부분 찾기

반응형

http://blog.naver.com/codecastle?Redirect=Log&logNo=100036823549

 

none MFC에서 memory leak난 부분 찾기

1.요약

MFC를 사용하지 않는 프로젝트에서 memory leak난 부분을 trace하는 방법을 설명.


2.본문

만약 MFC를 쓰지않고 프로젝트(exe)를 만들게 되면 MFC를 쓴 프로젝트와 같이 메모리릭이 일어난 소스코드의 파일과 라인넘버가 나오지 않게 된다. 이유는 우리가 MFC를 짠 프로젝트에서 new나 alloc을 할때 DEBUG모드에서는 특별한 함수가 실행되기 때문일텐데, 이부분이 MFC에 종속적이기 때문이었다.

그래서 MFC에서 쓰는 방법과 동일하게 new를 만들어 보기로 했다.

일반적으로 VC에서 클래스를 만들면 *.cpp에 다음의 코드가 추가 되어있다.


#ifdef _DEBUG 

#undef THIS_FILE 

static char THIS_FILE[]=__FILE__; 

#define new DEBUG_NEW 

#endif 

4번째 라인에 보면 "#define new DEBUG_NEW"와 같이 선언되어 있는것을 볼 수 있는데 만일 이 메크로가 실행된다면 모든 new가 DEBUG_NEW로 바뀌어서 컴파일 될 것이다.

그럼 DEBUG_NEW는 어떻게 되어있을까?

// afx.h 

#define 
 DEBUG_NEW new 
(THIS_FILE, __LINE__) 
// afx.h #define DEBUG_NEW new(THIS_FILE, __LINE__) afx.h에는 위와 같이 정의 되어있다. new의 인자로 위에서 정의한 THIS_FILE과 __LINE__가 들어간걸 볼 수 있다. 우리는 VC가 이걸 통해서 메모리릭이 발생된 지점을 찾는다는것을 예상할 수 있다.

그럼 우리도 stdafx.h 같은 곳에 위의 메크로를 추가하면 MFC에서와 같이 동작할 수 있다.

이렇게 만들어서 테스트해보니 여전히 메모리릭이 잡히지 않는 부분이 있었다. 이유는 new외에도 malloc을 써서 메모리를 활당한 부분이 소스코드에 있기 때문이었다.

그럼 malloc로 디버그 버전으로 정으하면 될것이다.

다음의 코드를 stdafx.h에 추가하였다.

#define DEBUG_MALLOC(size) _malloc_dbg(size, _NORMAL_BLOCK, __FILE__ , __LINE__) 
 
          그리고 각 *.cpp파일에 첨부되는 #define을 다음과 같이 수정하였다. 
#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#define malloc DEBUG_MALLOC

#endif

이제 모든 malloc은 DEBUG_MALLOC으로 바뀌게 되어 메모리릭을 트레이스할 수 있게 되었다.

하지만 이 클래스를 MFC를 쓰는 프로젝트에서 쓴다면 불필요하게 컴파일되는 부분이 #define malloc DEBUG_MALLOC 부분이다. 그래서 MFC를 쓰는 프로젝트에서는 이 메크로가 컴파일 되지않게 수정하였다.

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#ifndef _MSC_VER // MFC를 쓰는지 검사

#define malloc DEBUG_MALLOC

#endif

#endif



- 2001.08.19 Smile Seo -

 

 

 

원본 http://cafe.naver.com/jzsdn/4645
 
 

메모리 릭 memory leak 잡기 총정리.. (non MFC, win32)

#ifdef _MSC_VER
 #ifdef _DEBUG //memory leak test
  #include <crtdbg.h>
  #define malloc(a) _malloc_dbg(a,_NORMAL_BLOCK,__FILE__,__LINE__)
  inline void*  operator new(size_t size, LPCSTR strFileName, INT iLine)
   {return _malloc_dbg(size, _NORMAL_BLOCK, strFileName, iLine);}
  inline void operator delete(void *pVoid, LPCSTR strFileName, INT iLine)
   {_free_dbg(pVoid, _NORMAL_BLOCK);}
  #define new new(__FILE__, __LINE__)
  #define CHECK_MEMORY_LEAK _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
 #else
  #define CHECK_MEMORY_LEAK
 #endif //_DEBUG
#else
  #define CHECK_MEMORY_LEAK
#endif 





_CrtSetDbgFlag

Calling _CrtDumpMemoryLeaks is easy enough if your program always exits in the same place, but what if your program can exit from multiple locations? Instead of putting a call to _CrtDumpMemoryLeaks at each possible exit, you can include the following call at the beginning of your program:

          _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
          

This statement automatically calls _CrtDumpMemoryLeaks when your program exits. You must set both bit fields, _CRTDBG_ALLOC_MEM_DF and _CRTDBG_LEAK_CHECK_DF, as shown above.



_CRTDBG_ALLOC_MEM_DF : 디폴트로 켜져 있으며, 디버그 버전에서 모든 메모리 할당이 일어날 때마다 추적 가능하도록 특별한 기능을 추가해 둔다. 이 플랙이 켜져 있어야 메모리 누수를 안전하게 검사 할 수 있다.

_CRTDBG_LEAK_CHECK_DF : 프로그램이 완전히 종료되기 직전에 아직 해제되지 않은 메모리가 있는지 검사한다. 프로그램의 종료 포인트가 여러군데 있는 경우에 사용하면 일일이 _CrtDumpMemoryLeaks 메소드를 호출하지 않아도 자동적으로 메모리 누수를 검사할 수 있게된다.

'Study > C++' 카테고리의 다른 글

volatile  (0) 2010.05.29
mec++에 있는 auto_ptr  (0) 2010.05.28
__FILE__, __FUNCTION__, __LINE__  (0) 2010.03.25
c++ 생각하기 5.  (0) 2010.03.22
EnterCriticalSection 사용할때 주의 할점  (0) 2010.03.20
TAGS.

Comments