반응형
1. https://github.com/snoopspy/vmld
2. http://support.microsoft.com/kb/601929/ko (아래글 출처)
-------------------------------------------------------------------------------------------------------------------
이 문서는 이전에 다음 ID로 출판되었음: KR601929
2. http://support.microsoft.com/kb/601929/ko (아래글 출처)
-------------------------------------------------------------------------------------------------------------------
이 문서는 이전에 다음 ID로 출판되었음: KR601929
이 페이지에서
요약
Visual C++ 어플리케이션인 경우 디버그 빌드의 메모리 관련 함수를 사용하면 메모리 누수가 난 위치(파일명과 라인)를
Visual C++ 로부터 보고 받을 수 있습니다. 이들 메모리 함수에는_malloc_dbg, _calloc_dbg,
_realloc_dbg, _expand_dbg, _free_dbg, _msize_dbg 및 DEBUG_NEW 등이 있습니다.
추가 정보
MFC 가 보고하는 메모리 누수 정보
Visual C++ 의 MFC 프로그램을 개발중이라면 이 어플리케이션이 디버그 모드로 실행된 경우, 종료 시 디버그 창에 메모리 누수관련 정보가 다음과 같이 표시됩니다.Detected memory leaks! Dumping objects -> plex.cpp(31) : {173587} normal block at 0x03C02F00, 124 bytes long. Data: < P j > 00 00 00 00 00 00 00 00 C0 50 13 00 A8 6A 14 00 map_pp.cpp(72) : {173586} normal block at 0x03C02FB0, 68 bytes long. Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 {67576} normal block at 0x04021A80, 288 bytes long. Data: < L_ > 01 00 00 00 00 00 00 00 14 CB 4C 5F 01 00 CD CD {67575} normal block at 0x04021BD0, 288 bytes long. Data: < L_ > 01 00 00 00 00 00 00 00 14 CB 4C 5F 01 00 CD CD {63195} normal block at 0x03CB85E0, 124 bytes long. Data: < x J_ x J_> 0F 00 00 00 78 C2 4A 5F 19 08 05 96 78 C2 4A 5F strcore.cpp(118) : {56689} normal block at 0x03C4CB00, 19 bytes long. Data: < > 01 00 00 00 06 00 00 00 06 00 00 00 B0 C5 B7 A1 strcore.cpp(118) : {56679} normal block at 0x03C4B170, 19 bytes long. Data: < > 01 00 00 00 06 00 00 00 06 00 00 00 C1 D6 B0 A1 Object dump complete. The thread 0xDE has exited with code 0 (0x0). The program 'E:\Wow\BinD\Wow.exe' has exited with code 0 (0x0)
디버그 버전 메모리 함수
위의 내용에는 좌측에 파일 이름이 표시된 것이 있고 그렇지 못한 것이 있습니다. 파일 이름이 표시된 것은 디버그 빌드 메모리 함수를 이용하여 할당 받은 경우이고, 파일 이름이 없는 것은 그렇지 못한 경우입니다. 파일 이름을 표시하기 위해서는 요약에서 언급한 종류의 디버그 버전 함수를 사용해야 합니다.먼저, New 함수는 MFC 프로젝트에서 기본으로 디버그 버전을 사용하도록 되어 있으며 반드시 디버그 빌드인 경우에만 파일명이 표시됩니다. Release 빌드의 경우는 누수의 위치가 표시되지 않습니다. New 함수가 디버그 빌드가 적용되는 이유는 각 CPP 파일에 다음과 같은 라인이 첫 부분에 있기 때문입니다.
#ifdef _DEBUG #define new DEBUG_NEW #endif
#ifdef _CRTDBG_MAP_ALLOC #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) #define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) #define free(p) _free_dbg(p, _NORMAL_BLOCK) #define _msize(p) _msize_dbg(p, _NORMAL_BLOCK) #endif /* _CRTDBG_MAP_ALLOC */
#define _CRTDBG_MAP_ALLOC #include "crtdbg.h"
할당번호
‘MFC 가 보고하는 메모리 누수 정보’ 부분의 정보에서 “{“ 와 “}” 으로 둘러싸인 부분에 숫자가 있습니다. 이는 할당번호라고 하며 이를 이용해서 메모리 누수가 나는 곳으로 직접 Break Point 를 걸어 확인할 수도 있습니다.예를 들어, 다음과 같은 함수가 있습니다. 이 함수는 특정 할당번호를 갖는 위치의 malloc 함수에서 멈추어서 사용자가 그 위치를 확인하게 해 줍니다.
// testbreak.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <malloc.h> #include <crtdbg.h> int main(int argc, char* argv[]) { long allocReqNum; char *my_pointer; /* * Allocate "my_pointer" for the first * time and ensure that it gets allocated correctly */ my_pointer = (char*)malloc(20); _CrtIsMemoryBlock(my_pointer, 10, &allocReqNum, NULL, NULL); /* * Set a breakpoint on the allocation request * number for "my_pointer" */ _CrtSetBreakAlloc(allocReqNum+2); _crtBreakAlloc = allocReqNum+2; /* * Alternate freeing and reallocating "my_pointer" * to verify that the debugger halts program execution * when it reaches the allocation request */ free(my_pointer); printf("wow1\n"); my_pointer = (char*)malloc(10); free(my_pointer); printf("wow2\n"); my_pointer = (char*)malloc(10); free(my_pointer); }
이 방법은 할당 번호가 고정적으로 누수 된다고 보고되는 경우에만 사용가능 합니다.
MFC 이외의 어플리케이션
MFC 는 사용자가 특별히 작업을 해주지 않아도 메모리 누수를 보고해 주지만 그 외의 Visual C++ 함수인 경우는 메모리 누수를 보고해 주는 함수인 _CrtDumpMemoryLeaks() 를 사용합니다.콘솔 프로그램에서 누수보고 예제
// console.cpp : Defines the entry point for the console application. // #include "stdafx.h" /***************************************************************** * EXAMPLE 1 * * This simple program illustrates the basic debugging features * * of the C runtime libraries, and the kind of debug output * * that these features generate. * *****************************************************************/ #include <stdio.h> #include <string.h> #include <malloc.h> #include <crtdbg.h> // This routine place comments at the head of a section of debug output void OutputHeading( const char * explanation ) { _RPT1( _CRT_WARN, "\n\n%s:\n**************************************\ ************************************\n", explanation ); } // The following macros set and clear, respectively, given bits // of the C runtime library debug flag, as specified by a bitmask. #ifdef _DEBUG #define SET_CRT_DEBUG_FIELD(a) \ _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #define CLEAR_CRT_DEBUG_FIELD(a) \ _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #else #define SET_CRT_DEBUG_FIELD(a) ((void) 0) #define CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) #endif void main( ) { char *p1, *p2; _CrtMemState s1, s2, s3; // Send all reports to STDOUT _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); // Allocate 2 memory blocks and store a string in each p1 = (char*)malloc( 34 ); strcpy( p1, "This is the p1 string (34 bytes)." ); p2 = (char*)malloc( 34 ); strcpy( p2, "This is the p2 string (34 bytes)." ); OutputHeading( "Use _ASSERTE to check that the two strings are identical" ); _ASSERTE( strcmp( p1, p2 ) == 0 ); OutputHeading( "Use a _RPT macro to report the string contents as a warning" ); _RPT2( _CRT_WARN, "p1 points to '%s' and \np2 points to '%s'\n", p1, p2 ); OutputHeading( "Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations" ); _CrtMemDumpAllObjectsSince( NULL ); free( p2 ); OutputHeading( "Having freed p2, dump allocation information about p1 only" ); _CrtMemDumpAllObjectsSince( NULL ); // Store a memory checkpoint in the s1 memory-state structure _CrtMemCheckpoint( &s1 ); // Allocate another block, pointed to by p2 p2 = (char*)malloc( 38 ); strcpy( p2, "This new p2 string occupies 38 bytes."); // Store a 2nd memory checkpoint in s2 _CrtMemCheckpoint( &s2 ); OutputHeading( "Dump the changes that occurred between two memory checkpoints" ); if ( _CrtMemDifference( &s3, &s1, &s2 ) ) _CrtMemDumpStatistics( &s3 ); // Free p2 again and store a new memory checkpoint in s2 free( p2 ); _CrtMemCheckpoint( &s2 ); OutputHeading( "Now the memory state at the two checkpoints is the same" ); if ( _CrtMemDifference( &s3, &s1, &s2 ) ) _CrtMemDumpStatistics( &s3 ); strcpy( p1, "This new p1 string is over 34 bytes" ); OutputHeading( "Free p1 after overwriting the end of the allocation" ); free( p1 ); // Set the debug-heap flag so that freed blocks are kept on the // linked list, to catch any inadvertent use of freed memory SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF ); p1 = (char*)malloc( 10 ); free( p1 ); strcpy( p1, "Oops" ); OutputHeading( "Perform a memory check after corrupting freed memory" ); _CrtCheckMemory( ); // Use explicit calls to _malloc_dbg to save file name and line number // information, and also to allocate Client type blocks for tracking p1 = (char*)_malloc_dbg( 40, _NORMAL_BLOCK, __FILE__, __LINE__ ); p2 = (char*)_malloc_dbg( 40, _CLIENT_BLOCK, __FILE__, __LINE__ ); strcpy( p1, "p1 points to a Normal allocation block" ); strcpy( p2, "p2 points to a Client allocation block" ); // You must use _free_dbg to free a Client block OutputHeading( "Using free( ) to free a Client block causes an assertion failure" ); free( p1 ); free( p2 ); p1 = (char*)malloc( 10 ); OutputHeading( "Examine outstanding allocations (dump memory leaks)" ); _CrtDumpMemoryLeaks( ); // Set the debug-heap flag so that memory leaks are reported when // the process terminates. Then, exit. OutputHeading( "Program exits without freeing a memory block" ); SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); }
콘솔 프로그램에서 누수보고 예제 결과
G:\works\console\Debug>console Use _ASSERTE to check that the two strings are identical: ************************************************************************** G:\works\console\console.cpp(60) : Assertion failed: strcmp( p1, p2 ) == 0 Use a _RPT macro to report the string contents as a warning: ************************************************************************** p1 points to 'This is the p1 string (34 bytes).' and p2 points to 'This is the p2 string (34 bytes).' Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations: ************************************************************************** Dumping objects -> {45} normal block at 0x00431F40, 34 bytes long. Data: <This is the p2 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 32 20 73 {44} normal block at 0x00431F90, 34 bytes long. Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73 Object dump complete. Having freed p2, dump allocation information about p1 only: ************************************************************************** Dumping objects -> {44} normal block at 0x00431F90, 34 bytes long. Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73 Object dump complete. Dump the changes that occurred between two memory checkpoints: ************************************************************************** 0 bytes in 0 Free Blocks. 38 bytes in 1 Normal Blocks. 0 bytes in 0 CRT Blocks. 0 bytes in 0 Ignore Blocks. 0 bytes in 0 Client Blocks. Largest number used: 4 bytes. Total allocations: 38 bytes. Now the memory state at the two checkpoints is the same: ************************************************************************** Free p1 after overwriting the end of the allocation: ************************************************************************** memory check error at 0x00431FB2 = 0x73, should be 0xFD. memory check error at 0x00431FB3 = 0x00, should be 0xFD. DAMAGE: after Normal block (#44) at 0x00431F90. Perform a memory check after corrupting freed memory: ************************************************************************** memory check error at 0x00431FA0 = 0x4F, should be 0xDD. memory check error at 0x00431FA1 = 0x6F, should be 0xDD. memory check error at 0x00431FA2 = 0x70, should be 0xDD. memory check error at 0x00431FA3 = 0x73, should be 0xDD. memory check error at 0x00431FA4 = 0x00, should be 0xDD. DAMAGE: on top of Free block at 0x00431FA0. DAMAGED located at 0x00431FA0 is 10 bytes long. Using free( ) to free a Client block causes an assertion failure: ************************************************************************** dbgheap.c(1051) : Assertion failed: pHead->nBlockUse == nBlockUse Examine outstanding allocations (dump memory leaks): ************************************************************************** Detected memory leaks! Dumping objects -> {50} normal block at 0x00431EA0, 10 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD Object dump complete. Program exits without freeing a memory block: ************************************************************************** Detected memory leaks! Dumping objects -> {50} normal block at 0x00431EA0, 10 bytes long. Data: < > CD CD CD CD CD CD CD CD CD CD Object dump complete. G:\works\console\Debug>
속성
기술 자료: 601929 - 마지막 검토: 2004년 9월 21일 화요일 - 수정: 2.0
본 문서의 정보는 다음의 제품에 적용됩니다.
- Microsoft Visual C++ 6.0 서비스 팩 5
키워드: | kbhowto KB601929 |
더 이상 지원되지 않는 제품의 KB 내용에 대한 고지 사항
이 문서에서는 Microsoft에서 더 이상 지원하지 않는 제품에 대해 설명합니다. 따라서 이 문서는 "있는 그대로" 제공되며 업데이트되지 않습니다.
반응형
'Programming Language > C++,MFC' 카테고리의 다른 글
구조체 패딩(padding) 문제 (0) | 2014.10.24 |
---|---|
MFC 작업자 쓰레드(Worker Thread) 사용법 (0) | 2014.10.20 |
MFC 콤보박스 (0) | 2010.10.05 |
MFC에서 printf() 사용하기 (0) | 2010.07.16 |