Analysis of memory leak detection for CRT in C + + _c language

Source: Internet
Author: User
Tags diff

Even though the concept has been overused, it's a simple one to keep track of.

Copy Code code as follows:

#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;
}


The main principle is to use the CRT's memory debugging function, through the macro instead of the default operator new, let it be replaced by the following version:
Copy Code code as follows:

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;
}


In this way, the CRT records the file name and line number and size of the allocated memory, and finally when invoked with _CrtDumpMemoryLeaks (); If it's not released, it will print out.
The results are as follows:
Copy Code code as follows:

Detected memory leaks!
Dumping Objects->
F:\test\memleakchecker\memleakchecker\memleakchecker.cpp: {108} normal block at 0x0003a1a8, bytes long.
Data: < > CDs CD CD CD CD CD CD CD
F:\test\memleakchecker\memleakchecker\memleakchecker.cpp: {{} client block at 0x0003a160, subtype 0, Bytes long .
Data: < > CDs CD CD CD CD CD CD CD
F:\test\memleakchecker\memleakchecker\memleakchecker.cpp: {The} client block at 0x0003a120, subtype 0, 1 bytes long.
Data: < > 00
Object dump complete.

Here are some things to note:
(1) The role of #define _crtdbg_map_alloc
If you do not define this macro, the C-way malloc leaks will not be recorded.

(2) The role of the number {108} {107}
Represents the number of allocations, you can use the _CrtSetBreakAlloc program to run to the scheduled time to pause, such as

Copy Code code as follows:

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;
}


(3) If the program has multiple exits or involves global variables, you can use the _CrtSetDbgFlag set flag to let the program exit automatically print leaks, such as
Copy Code code as follows:

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;
}


(4) We know that the macro substitution is the most brutal way, so try to put the following new alternative macros into each CPP instead of a common header file, in fact, MFC is doing so
Copy Code code as follows:

#ifdef _DEBUG
#define NEW Debug_clientblock
#endif

(5) The operator new above can only take care of the most common new, in fact operator new has any number of overloads, just make sure that the first parameter is the size. For example, the following placement new will compile failure, because the macro replacement format does not meet the requirements, so if your CPP with non-standard new, do not add new detection macros.
Copy Code code as follows:

#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;
}


(6) because the tree in the STL map is used to placement new, if you use this to compile the failure:
Copy Code code as follows:

#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

#include <map>


You should put #include <map> in front of the macro definition.

(7) If you declare or define the operator new function after the macro #define new Debug_clientblock, you will fail the compilation because of the macro substitution.
The STL Xdebug file exactly affirms the operator new function, so make sure that the alternate macros for new are placed at the end of all include header files, especially after the STL header file.

Copy Code code as follows:

MyClass.cpp
#include "Myclass.h"
#include <map>
#include <algorithm>

#ifdef _DEBUG
#define NEW Debug_clientblock
#endif

Myclass::myclass ()
{
char* p = new char (' a ');
}


(8) If you think that the above new substitution macros are too cumbersome to be dispersed in each CPP, you want to put everything in a common header file, refer to the way defined below:
Copy Code code as follows:

MemLeakChecker.h
#include <map>
#include <algorithm>
Other STL file

#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


(9) Simple to determine whether a stand-alone function has a memory leak can be used in the following ways:
Copy Code code as follows:

Class Dbgmemleak
{
_CrtMemState M_checkpoint;

Public
Explicit Dbgmemleak ()
{
_CrtMemCheckpoint (&m_checkpoint);
};

~dbgmemleak ()
{
_CrtMemState checkpoint;
_CrtMemCheckpoint (&checkpoint);
_CrtMemState diff;
_CrtMemDifference (&diff, &m_checkpoint, &checkpoint);
_CrtMemDumpStatistics (&diff);
_CrtMemDumpAllObjectsSince (&diff);
};
};


int _tmain (int argc, _tchar* argv[])
{
Dbgmemleak check;
{
char* p = new char ();
char* pp = new char[10];
char* PPP = (char*) malloc (10);
}

return 0;
}


(10) Actually know the principle, write a set of C + + memory leak detection is not difficult, mainly overloaded operator new and operator delete, you can put each memory allocation is recorded in a map, delete records, When the final program exits, it prints out the map without delete. Of course we know that the CRT is actually tuned to malloc when implementing new, while malloc may be heapalloc, and HeapAlloc may be calling rtlallocateheap, so theoretically we can intercept and record at any level of these functions. But if you want to implement your own cross-platform memory leak detection, or overload operator new.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.