Detection of memory leaks in C++

巴扎黑
Release: 2016-11-30 11:24:50
Original
1187 people have browsed it

First we need to know whether the program has a memory leak, and then locate which line of code has the memory leak, so that we can fix it.

The easiest way is of course to use professional detection tools, such as BoundsCheck, which is well-known and very powerful. I believe that no one who develops C++ can do without it. In addition, it is not necessary. First, we need to know whether the program has a memory leak, and then locate which line of code has the memory leak, so that it can be repaired.

The easiest way is of course to use professional detection tools, such as BoundsCheck, which is well-known and very powerful. I believe that no one who develops C++ can do without it. In addition, you do not use any tools, but implement the monitoring of memory leaks yourself, which can be divided into the following two situations:

1. Detecting memory leaks in MFC

If you are using an MFC program, it is very simple. By default, there is memory leak detection function.

We used VS2005 to generate an MFC dialog box program and found that it can automatically detect memory leaks. We don’t need to do any special operations. After careful observation, we found that in each CPP file, there is the following code:

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

DEBUG_NEW This macro is defined in the afx.h file, which helps us locate memory leaks.

If the memory is not deleted after allocating memory in the cpp file containing the above code, then when the program is stopped, the Output window of VisualStudio will display the following information:

Detected memory leaks!
Dumping objects ->
d:codemfctestmfctest .cpp(80) : {157} normal block at 0x003AF170, 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.

Double-click the bold line in the Output window, then the IDE will Open the file and locate this line. It is easy to see where the memory leak occurs.

2. Detecting memory leaks in pure C++ programs

I tried the Win32 Console Application and Win32 Project projects created with Visual Studio, but the results were unable to detect memory leaks.

The following is a step-by-step process to establish the memory leak detection mechanism of the program.

First of all, we need to know that the Debug version of the C runtime library provides many detection functions to make it easier for us to debug the program. There is a special chapter in MSDN about this, called Debug Routines. I suggest you read the contents first.

We will use several very important functions in it. The most important one is _CrtDumpMemoryLeaks; see the help in MSDN for yourself. To use this function, you need to include the header file crtdbg.h

This function is only useful in the Debug version. When running the program under the debugger, _CrtDumpMemoryLeaks will display memory leak information in the "Output" window. Write a piece of code Try it out, as follows:

Detect memory leak version 1:

#include "stdafx.h"
#include
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int;
_CrtDumpMemoryLeaks;
return 0;
}

After running, the following information is displayed in the Output window:

Detected memory leaks!
Dumping objects ->
{112} normal block at 0x003AA770 , 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.

But this just tells us that the program has a memory leak, and it is hard to tell where it is leaked.

 Look at our memory leak detection version 2:

#include "stdafx.h"

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
int _tmain(int argc, _TCHAR* argv[])
{
int* p = new int;
_CrtDumpMemoryLeaks;
return 0 ;
}

This program defines several macros. The new in the Debug version is replaced by macros. The new new records the file name and code line when calling new. After running, you can see the following results:

Detected memory leaks!

Dumping objects ->
d:codeconsoletestconsoletest.cpp(21) : {112} client block at 0x003A38B0, subtype 0, 4 bytes long.
Data: < > 00 00 00 00
Object dump complete.

Haha, it has the same effect as the MFC program, but wait a minute. Take a look at the following code:

int _tmain(int argc, _TCHAR* argv[])

{
int* p = new int;
_CrtDumpMemoryLeaks;
delete p;
return 0;
}

You can find it after running We deleted the pointer, but it still reported a memory leak. So you can imagine that every time new is called, the call will be recorded internally in the program, similar to having an array record. If it is deleted, it will be deleted from the array, and _CrtDumpMemoryLeaks will print out the current status of the array. .

So in addition to dumping memory information when necessary, the most important thing is to use _CrtDumpMemoryLeaks once when the program exits;

If the program has more than one exit, then we need to call it in multiple places function.

Go further, what if the program deletes the pointer in the destructor of the class? For example:

#include "stdafx.h"
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
class Test
{
public:
Test { _p = new int; }
~Test { delete _p; }
int* _p;
};
int _tmain(int argc, _TCHAR * argv[])
{
int* p = new int;
delete p;
Test t;
_CrtDumpMemoryLeaks;
return 0;
}

You can see that the destructor is only called when the program exits, obviously not Memory leak, but this way of writing is still reported.

How to improve, see memory leak detection version 3:

#include "stdafx.h"
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
# Define_CRTDBG_MAP_ALLOC
#Include & lt; CRTDBG.H & GT;
#Ifdef _debug
#define New Debug_ClientBlock
#Endifehclass test
{
Public: PTest {_p = new int;}
~ test {delete _p;}
INT * _p;
};
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
int* p = new int;
delete p;
Test t;
return 0;
}

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); This statement automatically calls _CrtDumpMemoryLeaks when the program exits. _CRTDBG_ALLOC_MEM_DF and _CRTDBG_LEAK_CHECK_DF must be set at the same time.

In this way, this version has achieved the same effect as MFC, but I think this is not enough, because we only output information in the Output window, and the reminder to developers is not obvious , are often missed, and even if many people find a memory leak, it is not easy to repair, and it will not seriously affect the external performance of the program, so they will not repair it. How can developers proactively fix memory leaks? I remember that I once collaborated with someone to write a program. My function parameters had requirements and could not be empty, but others always passed null values. I had no choice but to verify the function parameters at the beginning of the function and assert them. In this way, when the program was running, it would always The assert kept popping up, which made debugging the program very stressful. Finally, other programmers got annoyed, so they fixed the problem and entered the parameters correctly. So I think that if we want programmers to take the initiative to do something, we must first make them feel that doing this can reduce their own burden and make their work easier. Haha, let's do the same. When the program exits, if a memory leak is detected, the program will prompt it.

See memory leak detection version 4:

#include "stdafx.h"

#include

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_ CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
void Exit
{
int i = _CrtDumpMemoryLeaks;
assert( i == 0);
}
int _tmain(int argc, _TCHAR* argv[])
{
atexit(Exit);
int* p = new int;
return 0;
}

This version will check for memory leaks when the program exits, if it exists A prompt dialog box will pop up.

atexit(Exit); sets the Exit function to be executed when the program exits. In the Exit function, if there is a memory leak, _CrtDumpMemoryLeaks will return a non-0 value and it will be asserted.

This version is ready for use. But we can still make some improvements, because if we really want to accurately detect all memory leaks in the code, we need to copy the #define... in the code to all files using new. It is impossible to copy so much code for each file, so we can extract it and put it in a file. For example, I put it in KDetectMemoryLeak.h. The content of the file is as follows:

#pragma once

#ifdef _DEBUG

#define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include
#include #ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

Then include KDetectMemoryLeak.h in the common file of the project. For example, for projects built with VS, include it in stdafx.h. Or I created a Common.h file myself, which contains some common code that is used by basically all files.

Related labels:
c
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template