본문 바로가기
Programming/Tips(C++,C#)

C++ 메모리 누수 탐지.

by 곰네Zip 2022. 7. 21.

원글 (마소독).

오.. 많은 기법이 추가되었다. C++에 손놓은지 벌써 근 10년.. (그동안 C#에 가있었어요)

그사이에 많은 기법이 추가되었다.

우선 공통적인건.. 메모리 누수를 찾기 위해 정보를 달라고 선언해야한다.

뭐.. '추적을 할테니 준비해달라' 이정도 선언?

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbgb.h>

그리고 디버그 정보를 추적할 준비해달라고 했으니 이제 정보를 캐야지.

프로그램 시작점 (전체 프로그램의 시작점. )

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

위 함수를 호출하여 디버그 플래그를 찍는다.

그리고 프로그램의 종료지점 (클래스 소멸자나 함수 끝이 아니다. 프로그램 종료다.)

_CrtDumpMemoryLeaks();

에 위 정보를 찍어주면 메모리 누수가 탐지되면 정보를 남겨준다.

메모리 정보에는 메모리번호와 누수정보만 남는다. 어느소스파일 몇번째위치에서 이 누수가 탐지되었는지는 알려주지 않는다. 이걸 가지고 어떻게 무슨일이 일어나는지 확인해보아야지. (아예 탐지했으면 어느소스인지도 좀 알려주지..)

 

1. 매크로를 사용하여 메모리 누수가 발생하는 위치 정보 얻기. (이걸 이제야 알았다니.. 알았다면 예전에 그 고생안했지.)

 new를 대체할 매크로를 하나 정의한다.

#ifdef _DEBUG
    #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
    // Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the
    // allocations to be of _CLIENT_BLOCK type
#else
    #define DBG_NEW new
#endif

물론 메모리 누수 탐지는 디버그 모드에서 돌려서 모두 잡고 릴리즈 해야하니까. 디버그모드에서만 돌면 된다.

(사실 위에 include랑 define도 디버그에서만 필요하다. 걔도 #ifdef _DEBUG로 분기컴파일 하자.)

그리고 프로그램에서는 모든 new생성자를 DBG_NEW 매크로로 생성하도록 변경하자. 

 그러면 메모리 누수 보고서에서 어디서 발생했는지 정보를 다 남겨준다. (역시 사람은 배워야.. 내 삽질의 시간..)

 

2. 메모리 할당 번호에 중단점 설정.

 메모리 할당 번호는 메모리 블록이 할당된 순서를 알려준다. 동일 step으로 진행하면 메모리 누수가 발생하는 위치의 메모리는 거의 같은 순서로 할당된다. 물론 항상 같은 위치를 잡는다고 보장할수는 없다. 해당 위치의 메모리가 몇번째로 할당될지는 정확하지 않다. 그래도 비교적 잘 잡힌다. 어디까지나.. 100%같은위치 보장은 안되니 참고.

 그리고 프로그램 종료 시, 메모리 누수가 탐지되면 해당 메모리번호를 기억하고.. 프로그램 시작지점에 

_CrtSetBreakAlloc(메모리할당번호);

위 코드를 넣고 빌드하면.. 메모리 누수가 탐지된 그 메모리 블럭번호가 할당되면 break가 걸린다.

그러면 거기서 메모리 누수가 날만한 부분 수정하고..

위의 _CrtSetBreakAlloc 주석처리하고 다시 실행 후 확인하기..

어.. 예전에 이렇게 삽질했다. 1번 방법을 알았다면 바로 코드 까서.. 누수될만한 부분 찾아서 수정했을거다... (역시 사람은 배워야해..)

그래도 메모리 누수 탐지해서 잡아냈으니 다행.. 

반응형

댓글