C++에서 Crt 의 메모리 누 출 검 측 에 대한 분석 소개
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int _tmain(int argc, _TCHAR* argv[])
{
char* p = new char();
char* pp = new char[10];
char* ppp = (char*)malloc(10);
_CrtDumpMemoryLeaks();
return 0;
}
그러면 Crt 는 이번에 분 배 된 메모리 의 파일 이름과 줄 번호,크기 등 을 기록 하고 마지막 으로 호출 용CrtDumpMemoryLeaks(); 아직 풀 리 지 않 으 면 인쇄 됩 니 다.결 과 는 다음 과 같다.
void *__CRTDECL operator new(
size_t cb,
int nBlockUse,
const char * szFileName,
int nLine
)
_THROW1(_STD bad_alloc)
{
/* _nh_malloc_dbg already calls _heap_alloc_dbg in a loop and calls _callnewh
if the allocation fails. If _callnewh returns (very likely because no
new handlers have been installed by the user), _nh_malloc_dbg returns NULL.
*/
void *res = _nh_malloc_dbg( cb, 1, nBlockUse, szFileName, nLine );
RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));
/* if the allocation fails, we throw std::bad_alloc */
if (res == 0)
{
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return res;
}
다음은 주의사항 이다.(1)\#defineCRTDBG_MAP_ALLOC 의 역할 은 이 매크로 를 정의 하지 않 으 면 C 방식 의 malloc 유출 이 기록 되 지 않 습 니 다.(2)숫자{108}{107}의 역할 은 몇 번 째 분 배 를 나타 내 며CrtSetBreakAlloc 프로그램 이 예 정 된 횟수 로 실 행 될 때 일시 정지 합 니 다.예 를 들 어
Detected memory leaks!
Dumping objects ->
f:\test\memleakchecker\memleakchecker\memleakchecker.cpp(23) : {108} normal block at 0x0003A1A8, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
f:\test\memleakchecker\memleakchecker\memleakchecker.cpp(22) : {107} client block at 0x0003A160, subtype 0, 10 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD
f:\test\memleakchecker\memleakchecker\memleakchecker.cpp(21) : {106} client block at 0x0003A120, subtype 0, 1 bytes long.
Data: < > 00
Object dump complete.
(3)프로그램 에 여러 개의 출구 가 있 거나 전역 변수 가 있 으 면CrtSetDbgFlag 설정 로 고 는 프로그램 이 종 료 될 때 자동 으로 인쇄 되 어 유출 됩 니 다.예 를 들 어
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetBreakAlloc(108);
char* p = new char();
char* pp = new char[10];
char* ppp = (char*)malloc(10);
_CrtDumpMemoryLeaks();
return 0;
}
(4)매크로 대체 가 가장 거 친 방식 이라는 것 을 알 고 있 기 때문에 아래 new 대체 매크로 를 모든 Cpp 에 넣 는 것 이 일반적인 헤더 파일 에 넣 는 것 이 아니 라 실제 MFC 도 이렇게 했 습 니 다
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
char* p = new char();
char* pp = new char[10];
char* ppp = (char*)malloc(10);
return 0;
}
(5)위의 operator new 는 가장 일반적인 new 만 고려 할 수 있 습 니 다.실제로 operator new 는 여러 가지 과부하 방식 이 있 으 며,첫 번 째 매개 변 수 는 크기 를 표시 하 는 것 임 을 확인 해 야 합 니 다.예 를 들 어 아래 placement new 는 컴 파일 에 실 패 했 습 니 다.매크로 대체 후 형식 이 요구 에 부합 되 지 않 기 때문에 CPP 가 표준 이 아 닌 new 를 사용 했다 면 new 검 측 매크로 를 추가 하지 마 십시오.
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
(6)STL 에 맵 에 있 는 tree 가 placement new 를 사 용 했 기 때문에, 그래서 이렇게 사용 하면 컴 파일 에 실 패 했 습 니 다.
#include <new>
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
char* p = new char();
char* pp = new char[10];
char* ppp = (char*)malloc(10);
char d;
char* p1 = new(&d) char('a');
return 0;
}
\#include