기본 콘텐츠로 건너뛰기

How to manage memory leaks?

Visual C++ Debugging: memory leak 어떻게 관리할 것인가?


Q: memory leak 이란 무엇인가?

A:
이전에 할당된 memory 정확한 해제 실패.


Q: memory leak
어떤 영향을 미치나?


A:
많은 양의 memory leak되거나 점진적으로 leak 생기는 Program들은 성능저하(점진적으로 감소)에서부터 memory 완전히 고갈되는 현상이 점진적으로 잦아지는 현상을 보일 것이다.  심하게는 leak 되는 program 다른 program fail 정도의 엄청난 memory 사용하게 될것이며, 사용자들은는 문제가 어디 있는지 알지 못한채 떠나버릴것이다. 추가로, 아무 해가 없는 memory leak 조차도 점진적인 다른 문제를을 유발할 것이다.


Q: memory leak
어떻게 유발되어지는가?



A:
여려가지 원인이 있다. :

  • Pointer 범위를 벗어날 :

Code:

 

void foo()

{

  int *i = new int;

  *i = 44;

}


또는

Code:

 

{

  char* str = new char[20];

  strcpy(str,"memory leak");

}




  • Pointers 잃어버렸을 .

Code:

 

class Sample

{

  int* val;

 

public:

  Sample()

  {

    val = new int;

    *val = 44;

  }

 

  ~Sample()

  {

    delete val;

  }

};

 

void foo()

{

  Sample* a = new Sample;

  Sample* b = new Sample;

  a = b;

 

  delete a; // 이때 b도 사실상 삭제되었다.

 

//delete b; // 이미 삭제됨.
}




  • new/delete 잘못 사용했을 .

Code:

 

double* d = new double[10];

 

delete d; // delete d[0];

            // must use delete [] d;




  • delete mismatch

Code:

 

int *i;

while(someCondition)

{

  i = new int;

  // some code

}

delete i;



Q:
program 있는 memory leak 어떻게 찾을 있을까?


A: degug
상태에서 program 실행시켰을 , '_CrtDumpMemoryLeaks()' output 창에 memory leak 정보를 표시한다. Memory leak정보는 아래와 같다.

Code:

 

Detected memory leaks!

Dumping objects ->

D:\VisualC++\CodeGuru\MemoryLeak\MemoryLeak.cpp(67) : {60}

normal block at 0x00324818, 4 bytes long.

Data: <,   > 2C 00 00 00

Object dump complete.


만약 ‘stdafx.h’ 기본적으로 포함되는 ‘afx.h’내의  'crtdbg.h' 정의된 '#define _CRTDBG_MAP_ALLOC' 문을 사용하지 않았다면, memory leak dump 아래와 같이 보이게 될것이다.

Code:

 

Detected memory leaks!

Dumping objects ->

{60} normal block at 0x00324818, 4 bytes long.

Data: <,   > 2C 00 00 00

Object dump complete.


'_CRTDBG_MAP_ALLOC'
정의 되지 않으면, 아래와 같이 보일것이다. :

  • 메모리 할당 번호(중괄호내에).
  • Block type (normal, client, or CRT).
  • 16진수 형태의 memory 위치.
  • Block 크기(bytes).
  • 처음 16byte 내용(16진수).

'_CRTDBG_MAP_ALLOC' 정의 하면, memory leak되는 곳의 file까지 보여준다. 파일이름에  추가로 따라오는 번호는  file 내부에 있는 line 번호이다.

Q: What is the effect of using '_CRTDBG_MAP_ALLOC' on the C++ 'new' and 'delete' operators?

C++ ‘new’ ‘delete’에서  '_CRTDBG_MAP_ALLOC' 사용했을때의 효과는 무엇인가?


A: application에서 debug모드로 '_CRTDBG_MAP_ALLOC' flag 정의 하면, heap function들의 기본 버전은 debug모드로 mapping된다. flag '_DEBUG' flag 정의되어 있을때만 사용 가능하다.

C run-time libraty
debug 버전에는 C++ 'new' 'delete' 대한 debug 버전을 포함하고 있다. 만약
C++
에서 'CRTDBG_MAP_ALLOC' 정의 하였다면, new 모든 instance 모든 source file line 정보에 대해 기록을 남기는 debug버전으로 mapping 된다.  .

만약 '_CLIENT_BLOCK' 할당 형태로 사용하길 원한다면, 'CRTDBG_MAP_ALLOC' define 하지 마라. 대신에,  'net' Debug버전을 직접 호출하거나, 아래의 예에서 처럼 debug 모드에서의 'new' 대치 할수 있는 macro 만들어 써야 한다.  'delete' debug버전은 보든 block type들에서 동작하고 release 버전에서도 program 수정이 필요하지 않다.

Code:

 

// DbgNew.h

// Defines global operator new to allocate from client blocks

 

#ifdef _DEBUG

   #define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)

#else

   #define DEBUG_CLIENTBLOCK

#endif

 

 

// MyApp.cpp

// Compile options needed: /Zi /D_DEBUG /MLd or use a

// Default Workspace for a Console Application to build a debug version

 

#include <crtdbg.h>

#include <dbgnew.h>

 

#ifdef _DEBUG

#define new DEBUG_CLIENTBLOCK

#endif

 

int main( )  

{

   int* array = new int[10];

   _CrtMemDumpAllObjectsSince(NULL);

 

   return 0;

}




Q: memory leak
검출 하는데 도움이되도록 heap 상태나 내용을 보고해주는'CRT'기능이 있나?

A:  'crtdbg.h'
내에 다음과 같은 구조체가 정의 되어있다. :

Code:

 

typedef struct _CrtMemState

{

        struct _CrtMemBlockHeader* pBlockHeader;//최근 할당된 block을 위한 pointer
        unsigned long lCounts[_MAX_BLOCKS];// block의 5type들에 대한 각각의 counter

        unsigned long lSizes[_MAX_BLOCKS]; //할당된 각각의 block type들의 총 byte
        unsigned long lHighWaterCount; //특정시점에서 지금까지 가장 많이 할당된 byte
        unsigned long lTotalCount;    //현재 할당된 총 byte

} _CrtMemState;


이 구조체는 debug heap linked list (가장 최근에 할당된) 첫번째 block pointer로 저장한다. 그런 후, 두 개의 배열 내에 리스트 내 각각의 memory block('_NORMAL_BLOCK', '_CLIENT_BLOCK', 'FREE_BLOCK' ) 이 얼마나 많은 지와 각각의 block에 할당된 byte를 기록한다. 마지막으로, 전체 heap에서 해당 시점까지 할당된 byte들의 가장 많은 횟수와 현재 할당된 byte들의 수를 기록한다.

 

아래의 function들은 heap의 상태와 내용을 기록하고 memory leak과 다른 문제들을 감지하기 위해 정보들을 이용한다.

  • 'CrtMemCheckpoint' ->application 의해 지원되는 '_CrtMemState'구조체로 heap 스냅샷을 저장한다.

  • '_CrtMemDifference' ->두개의 memory 상태 구조체를 비교하고, 차이점을 또다른 구조체에 저장하며, 두개의 구조체 상태가 다르면 ‘TRUE’ return한다.


  • '_CrtMemDumpStatistics' ->  주어진 '_CrtMemState' 구조체를 dump한다. 구조체는 해당 시점의 debug heap 상태의 스냅샷을 포함하거나 스냅샷의 차이점에 대한 정보를 포함할 것이다.

Code:

 

_CrtMemState s1, s2, s3;

 

_CrtMemCheckpoint( &s1 );

// memory allocations take place here

_CrtMemCheckpoint( &s2 );

 

if ( _CrtMemDifference( &s3, &s1, &s2) )

   _CrtMemDumpStatistics( &s3 );




  • '_CrtMemDumpAllObjectsSince' -> heap에서 가져온 스냅샷 또는 실행 시작으로부터 주어진이래로 모든 할당된 object들에 대한 정보를 dump한다. 만약 ‘_CrtSetDumpClient’ 이용하여 설치되었다면, 시간 '_CLIENT_BLOCK' block dump하며, application 의해 지원되는 hook function 호출한다.
  • '_CrtDumpMemoryLeaks':  program 실행이 시작된 이래로 memory leak 일어났는지에 대한 여부를 결정하고, 만약 그렇다면, 모든 할당된 object들을 dump한다. 만약 '_CrtSetDumpClient' 사용하여 설치되었다면,  시간 '_CrtDumpMemoryLeaks' '_CLIENT_BLOCK' block dump하며, application에서 지원하는 hook function 호출한다.



Q: memory leak
정보를 어떻게 dump할까요?


A:
당신은 아래의 문장을 여려분 program 내에 포함시킴으로써 memory leak 정보를 dump 있다. :

Code:

 

#include <iostream>

 

#define _CRTDBG_MAP_ALLOC

#include <crtdbg.h>

 

int main()

{

   int* array = new int[10];

   _CrtDumpMemoryLeaks();

   return 0;

}




Q: MFC
에서 어떻게 memory leak 감지 있을까?


A:
다음과 같이 있다. :

  • Memory 할당 추적 : ‘DEBUG_NEW’ macro memory leak들을 찾아낼 있다.
  • Memory 진단 기능: : 진단 추적을 하고 특정 memory ‘afxMemDF’ 함께 진단한다.
  • Memory 스냅샷 가져요기 : 'CMemoryState’으로 스냅샷을 찍는다.
  • Memory 통계 보기: 'CMemoryState:: Difference' 'CMemoryState:: DumpStatistics'
  • Object Dump : 'CMemoryState:: DumpAllObjectsSince'



Q:
예제 얻을 있을까?


A:
예제는 memory leak 찾는데 도움이 되는 memory 스냅샷을 어떻게 가죠오는지를 보여주는 예제이다. Memory 체크 문장은 #ifdef _DEBUG / #endif 싸여져야 Win32 Debug버전에서 Compile 된다는 것에 주의하라.

Code:

 

#ifdef _DEBUG

   CMemoryState oldMemState, newMemState, diffMemState;

   oldMemState.Checkpoint();

#endif

 

   // Do your memory allocations and deallocations.

   CSite* p = new CSite( "CodeGuru", "http://www.codeguru.com");

 

#ifdef _DEBUG

   newMemState.Checkpoint();

   if( diffMemState.Difference( oldMemState, newMemState ) )

   {

      TRACE( "Memory leaked!\n" );

   }

#endif




Q:
어떻게 하면 memory leak 피할 있을까?


A:
명심할것:

  • 'new'/'delete' 'new[]'/'delete[]' 올바르게 사용할 (또한, 'malloc'/'free')
  • pointer들은 memory 해지를 하기 전에 범위를 벗어나지 않는다.
  • loop에서 memory 할당되었다면, release 매번 해야한다.

 원본 : http://www.codeguru.com/forum/showthread.php?t=312742

댓글

이 블로그의 인기 게시물

각도 단위 변환

(1) 각도의 기본 단위 각도를 나타내는 단위입니다. 360분법 으로 표시하는 1도는 사방을 360으로 나눈 크기입니다. 1분은 1도를 60등분한 각이고 1초는 1분을 다시 60등분한 크기입니다. 분(arcminute)과 초(arcsecond)는 시간을 나타내는 단위인 분(minute), 초(second)와 기호가 같은데, 천문학(영어)에서는 둘을 구분하기 위해 각도는 나타내는 단위에는 ' arc- '를 붙여 표기합니다. 각도를 나타내는 다른 방법으로 호도법 이 있습니다. 호도법은 반지름에 대한 호의 길이 단위로 각도를 표시하는 방법으로 사방은 원주율(π)의 2배 크기가 됩니다(360° = 2π rad). 호도법으로 나타낸 각도는 라디안(radian)으로 표시하며, 360분법으로 나타낸 각도를 호도법으로 나타낸 각도로 바꾸어 주려면 360분법으로 나타낸 각도에 π/180을 곱해주면 됩니다. 컴퓨터 프로그램 언어에서 삼각함수를 계산할 때에는 주로 호도법은 쓰고 있습니다. 1도(˚ , degree) : 1˚ = 60′ = 3600″ = π/180 rad 1분(′, arcminute) : 1′ = 60″ = 1/60° 1초(″, arcsecond) : 1″ = 1/60′ = 1/3600° 1라디안(rad, radian) : 1 rad = 180/π° (π = 원주율 = 3.1415926535897932384626433832795) (2) 시간의 기본 단위 시간의 기본단위는 초(second)입니다. 1초는 국제 표준으로 정밀하게 정의되어 있는데, 세슘 원자(세슘-133)가 9,192,631,770번 진동하는 동안의 시간으로 정의되어 있습니다. 본래 1초는 1 평균 태양일의 1/86400로 정의되어 있었지만 지구의 자전 주기는 다소 불규칙하고 느리게 바뀌고 있으므로 균일한 시간을 정의하기에는 부족합니다. 이후 1초는 지구의 공전 주기를 바탕으로 다시 정의 되었다가 지금은 세슘 원자의 특성을 기반으로 새롭게 정의하여 ...

Cramer rule - 크래머 공식

  크래머 공식 (Cramer's rule)은 선형연립방정식의 해를 행렬식 으로 표현하는 선형대수학 의 정리(theorem)이다. 이름은 가브리엘 크래머 (Gabriel Cramer) (1704 - 1752)에게서 유래한다.     방정식이 많은 경우의 실제 해의 계산에 있어서는 그리 유용하지 않지만, 피봇팅(pivoting)이 필요하지 않은 경우 작은 크기의 행렬에서는 가우스 소거법보다 훨씬 효율적이다. 크래머 공식은 연립방정식의 해를 외재적으로 표현하기 때문에 이론의 전개에 유용하다.   연립방정식이 다음과 같은 행렬 간의 곱으로 표현될 때. A x = c   식에서 정사각행렬 (square matrix) A 는 역행렬을 갖고, 벡터 x 는 ( x i ) 를, 벡터 c 는 ( c i ) 를 성분으로 갖는 열벡터이다.   정리는 다음과 같다. 식에서 A i 는 A 의 i 번째 열을 열벡터 c 로 대체한 행렬을 말한다.     예 [ 편집 ] 2x2 행렬에서 공식을 적용해 보면, 주어진 연립방정식이 다음과 같을 때, a x + b y = e c x + d y = f , 이 식은 로 쓸 수 있으며, 공식을 적용하면, 이 된다.         미분기하학에 적용 [ 편집 ]   크래머 공식은 미분기하 문제를 풀 때 매우 유용하다. 두 개의 방정식 , 이라 가정한다. 여기서, u 와 v 는 독립 변수이고, , 라 정의한다.   여기서 의 방정식을 찾는 것은 크래머 공식으로 해결할 수 있다.   첫째 , F,G,x,y 의 미분을 계산한다. dF, dG 에 dx 와 dy 를 대입하면   u 와...

CTE(Coefficient of Thermal Expansion: 열팽창 계수)

열변형량 계산표.xlsx         측정기기에 대해서 1. 사용 환경은 20℃으로 설정하지 않으면 안되나요?   그런 일은 없겠지만, 물건은 온도가 높아지면 팽창하고, 낮아지면 줄어듭니다. 거기서 공업적 길이를 나타내는 경우에 표준 온도 20℃으로 결정해 그 온도에 있어서의 결과를 나타내게 되어 있습니다. 그것은 ISO 1에 의해, 「길이 측정의 표준 온도는 20℃으로 한다」라고 규정되고 있습니다. 단, 이 규격에는 20℃에 대한 허용치는 나타나지 않습니다만, 별도인 규격으로 예를 들면 JIS Z 8703에서는 광공업에 있어서의 시험(측정이나 측정기의 교정도 포함된다)을 실시하는 장소의 온도에 관한 표준 상태의 허용차이가 규정되고 있습니다.   표준 온도의 허용차이 급별 허용차이 ℃ 온도 0. 5급 ± 0.5 온도 1급 ± 1 온도 2급 ± 2 온도 5급 ± 5 온도 15급 ± 15   즉, 항상 20℃에 정확히 맞추는 것은 매우 곤란해서, 어느 허용차이의 온도 환경이 필요하게 될까는 어느 정도의 정확한 측정이나 시험을 실시하느냐에 달려있다고 봅니다. 고정밀도의 측정을 실시하려면 , 허용차이의 작은 온도 환경이 요구됩니다.   2. 선열팽창 계수를 가르쳐 주세요?   물건은 온도가 높아지면 팽창하고 낮아지면 줄어듭니다. 온도 변화에 의한 물체의 길이의 증감을 수치화한 것이 선열팽창 계수입니다. 아래와 같이에 당사제품의 선열팽창 계수를 몇개인가 올려 보고 싶다고 생각합니다. 제품명 정밀도에 영향을 주는 주요 부분의 재질 선열팽창 계수 게이지 블록(스틸) 강 10.8 X 10 -6 K -1 게이지 블록(세라믹) ...