Simple Memory Leak tracking (1) debug_new Solution

Source: Internet
Author: User
Preface

Memory Leak in C ++ encoding is a very annoying but lingering topic. Recently, due to the introduction of GC, in order to verify whether GC is indeed normal and free of memory, therefore, a tracer for memory allocation is provided first.

Different from the distributor, the distributor mainly solves two problems:

1. Performance, pool-based allocation often provides much faster performance than direct virtual allocation. It is said that this principle is invalid after Vista, because Microsoft modified the implementation mechanism of VA, but it was said that there was no actual test.

2. Fragment. Avoid a large amount of scattered memory allocation to free up its continuous memory. As a result, the subsequent memory cannot be allocated because there is no continuous block.

Our tracker tracer mainly aims to solve a problem, that is, when the memory is allocated, when it is deleted, and when the program is exited.

Solution 1: debug_new Solution

Basically, many predecessors have written this topic before, and there is no solution beyond those of the predecessors here. I just learned and understood it when I made this module.

There are two comparative solutions for this problem. One is the debug_new solution of MFC, which is also used by Max SDK.

In fact, the principle is very simple. As long as we can get the file name and row number of the current statement, and then when we are new, we ask our tracer to record the current address and bind it with the file name and row number, then, delete the record according to the address.

How to implement it?

This problem is nothing more than solving two problems. First, we need to take over new things before recording our own information.

Operator new of C ++ can be overloaded in different forms, for example:

void* operator new (size_tInSize, const char* InLogMsg){    std::cout << InLogMsg <<std::endl;    return ::malloc(InSize);}

When this overload is called, new needs to be adjusted as follows:

Int * P = new ("I am allocating memory") int;

Note that new and operator new are not the same thing. After operator new is provided in a special form, a similar operator delete must be provided accordingly. Otherwise, level 1 warning will occur.

If you are interested in this question, we can see Supplement 1 at the end of this article. It has nothing to do with the topic of this article and is temporarily ignored.

The second question is, how do we know the file and flight of the current statement?

C ++ can use the following method to obtain the file and row number of the current statement:

STD: cout <"the current file is:" <__ file _ <". The current row number is: "<_ line __< <STD: Endl;

Preparations are ready to begin!

First, we need to provide a tracer to record the file name and row number information:

class TracerFileLn{public:    TracerFileLn& singleton();private:    struct _AllocInfo    {        const char*filename_;        size_tfileLn_;    };    typedefstd::hash_map<qword, _AllocInfo>alloc_hash;    alloc_hashallocInfoHash_;public:    void traceMalloc(void* InPtr, const char* InFilename, size_t InFileLn)    {        _AllocInfosAllocInfo = { InFilename, InFileLn };        allocInfoHash_.insert( alloc_hash::pair((qword)InPtr, sAllocInfo) );    }    void traceFree(void* InPtr)    {        auto it = allocInfoHash_.find(InPtr);        allocInfoHash_.erase(it);    }};

So, can we provide the next new overload?

Void * operator new (size_tinsize, const char * infilename, size_t infileln)

Then, operator new is implemented as follows:

void* operator new(size_t InSize, const char* InFilename, size_t InFileLn){    void* pPtr = ::malloc(InSize);    TracerFileLn::singleton().traceMalloc(pPtr, InFilename, InFileLn);    return pPtr;}

Then, operator Delete needs to be implemented as follows:

void operator delete(void* InPtr){    TracerFileLn::singleton().traceFree(InPtr);}void operator delete(void* InPtr, const char* InFilename,size_t InFileLn){    TracerFileLn::singleton().traceFree(InPtr);}

Remember that new [] and delete [] must be implemented accordingly.

In this case, we can no longer use the native New of C ++, but must use the new.

Int * pptr = new (_ file __,__ line _) int;

It's too much trouble to write all the places where new is used? However, this is not difficult. If we have a macro, it's like the MFC debug_new:

# Define debug_new new (_ file __,__ line __)

# Define new debug_new

Then, the new location will be replaced with new (_ file __,__ line.

Int * pptr = newint;

You can continue to write this statement, but before this sentence, you must ensure that there is a macro definition of # define new debug_new in front of it.

The information is traced. After the program ends, you only need to check which allocinfo exists in the hash, and the corresponding memory leakage can be found by dumping them one by one.

It looks very convenient, right? It is not convenient. We will continue to expand later.

Supplement 1: After providing the new operator new, why should we provide the corresponding operator delete? According to the C ++ standard, the object construction can be abnormal. If the construction is abnormal, the current object should be recycled. If you use a custom format for the new object, when the constructor is abnormal, C ++ recycles the object using the delete statement in the corresponding custom format, therefore, the corresponding operator delete must be provided. Otherwise, the memory will not be recycled. \ But if everything is normal, which delete is called when you manually call delete? The answer is the standard Delete: void operator Delete (void * inptr). In addition, new and operator new are not the same thing? Yes, new is the c ++ keyword. What is new doing? 1. Call operator new in the corresponding form to allocate memory. 2. Call placement new, which is the object constructor to construct the object. That is, there are two steps for new. The first step is Operator new, and operator new only allocates memory, regardless of anything else.

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.