최상단 광고

2012년 4월 8일 일요일

치명적인 Memory leak...


 Memory leakage... C++, C를 사용하는 사람들은 늘 자주자주 보는 문제입니다. 사실 분명히
내가 짠 코드는 이런 누수현상이 없다라구 하구 또 많은 Tool들을 통해서 찾는다고 하지만 사실 해법이 마땅히 없는 것은 사실입니다.

   최근에는 DevPartner에서 코드오류를 낸다는 부분 때문에 delete하는 부분을 지웠다가 옴팡지게 Memory leakage의 오명을 뒤집어 쓰고 결국 Team전체에 케익을 사는 엄청난 댓가를 치루고 말았습니다. 결국 DevPartner같은 Tool들도 못믿는다는 이야기입니다. 게다가 이런 Tool들은 무지하니 많은 Message를 내보내기는 합니다만 궁극적으로 중요한 정보를 찾을 수 없게 할 경우도 있습니다.

  http://www.codeproject.com/cpp/MemFailTest.asp에 보면 이것들을 매우 저렴하게(?)잘 해결할 수 있는 방법이 나옵니다. 어떻게 하는 것일까요?

 우선 우리가 만드는 new, malloc같은 것들이 잡는 것은 전체 메모리 영역에서 만드는 것이 아니라 heap이라는 영역에서 메모리를 잡는 것입니다. 일반적으로 Win32 system은 4G memory를 잡고 있습니다. 2G는 OS가 미리 점유하고 있고 나머지 2G를 사용하는 것입니다. 이 안에 사용자가 잡았다가 날렸다가 하는 영역이 바로 heap입니다.

 이 영역들을 분석해주는 함수들을 이용하면 됩니다. 단 아래 소개하는 Function들은 Windows에 해당하는 이야기입니다. UNIX에서는 다른 것으로 알고 있습니다.

 아래 예제로 설명해 드리겠습니다.

==================================
#include
#include
#include
#ifndef _CRTBLD
#define _CRTBLD
#include
#endif  //꼭꼭 위의 헤더파이들을 추가해 주세요. 

int main(void)
{
   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT );


   _CrtMemState memstate1, memstate2, memstate3 ; // 메모리 상태를 알려주는 구조체들입니다. 
   _CrtMemCheckpoint(&memstate1) ; // 메모리 상태를  memstate1에 기록합니다. 


    int *x = new int(1177) ;// allocated
    char *f = new char[50] ; // allocated
    strcpy(f, "Hi Naren") ;
    delete x ; // freed, 
    _CrtMemCheckpoint(&memstate2) ; // 메모리 상태를  memstate2에 기록합니다.

    //두개의 Memory 상태 구조체를 비교합니다. 현재 char* f block을 지우지 않았습니다.
   //그러므로 이것 떄문에 debug heap에 의해 error를 잡아내야 합니다.
   if(_CrtMemDifference(&memstate3, &memstate1, &memstate2))  //문제가 있으면 true를 return 합니다. 
   {   
      printf("\nOOps! Memory leak detected\n") ;
      _CrtDumpMemoryLeaks() ;
      //대신에 _CrtMemDumpAllObjectsSince()를 이용할 수도 있습니다.
   }
   else
      printf("\nNo memory leaks") ;
      return 0 ;
}
==================================


위의 예제를 돌리면 Visual Studio Output 윈도우에 아래처럼 뜹니다.
===========================================
OOps! Memory leak detected
Detected memory leaks!
Dumping objects ->
{42} normal block at 0x002F07E0, 50 bytes long.
Data: 48 69 20 4E 61 72 65 6E 00 CD CD CD CD CD CD CD
Object dump complete.
===========================================

위의 data값들을 가지고 찾아보면 됩니다. 한데 맨날 이렇게 어렵게어렵게 해야 될까요?
아래 코드들은 위의 방법들을 또 잘 정리해놓은 것들입니다. 더 자세하게 해서 Blog에 올려놓을께요.

댓글 없음: