Memory leakage detection in C ++

Source: Internet
Author: User
Memory leakage detection in C ++

First, we need to know whether the program memory has been leaked, and then find out which line of code has been leaked in order to fix it.

Of course, the simplest method is to use professional detection tools, such as boundscheck, which is very powerful. I believe that developers who develop C ++ cannot do without it. In addition, instead of using any tool, you can monitor memory leakage by yourself. There are two scenarios:

1. Detect Memory leakage in MFC

For example, it is very simple to use an MFC program. By default, the memory leakage detection function is available.

We used vs2005 to generate an MFC Dialog Box program and found that it can automatically detect memory leakage. we do not need to perform any special operations. after careful observation, the following code is found in each CPP file:
# Ifdef _ debug
# Define new debug_new
# Endif

The macro debug_new is defined in the afx. h file, which helps us locate Memory leakage.

If the memory is not deleted after the CPP file contains the above Code is allocated, when the program is stopped, the output window of Visual Studio will display the following information:
Detected memory leaks!
Dumping objects->
D: \ code \ mfctest. cpp (80): {157} normal block at 0x003af170, 4 bytes long.
Data: <> 00 00 00 00
Object dump complete.

Double-click the line in the output window, and IDE will open the file and locate the line. It is easy to see which memory leakage occurs.

2. Detect pure C ++ program memory leakage

I tried the Win32 console application and Win32 project projects created using Visual Studio, and the results cannot detect memory leakage.

Next, we will establish a mechanism for detecting program memory leaks.

First, we need to know that the debug version of the C Runtime Library provides a lot of detection functions, making it easier for us to debug programs. In msdn, there is a special chapter about this, called debug routines. We suggest you take a look at the content.

We will use several important functions. Among them, the most important is _ crtdumpmemoryleaks. Let's take a look at the help in msdn. To use this function, you must include the header file crtdbg. h.

This function is only available in the debug version. When you run a program under the debugger, _ crtdumpmemoryleaks will display Memory leakage information in the "output" window. test the code by writing a segment, as shown below:

Detected Memory leakage version 1:
# Include "stdafx. H"
# Include <crtdbg. h>
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.

However, this only tells us where the program memory is leaked and it cannot be seen at a glance.

Let's look at our detection Memory leakage 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 <crtdbg. h>
# Ifdef _ debug
# Define new debug_clientblock
# Endif
Int _ tmain (INT argc, _ tchar * argv [])
{
Int * P = new int;
_ Crtdumpmemoryleaks;
Return 0;
}

The program defines several macros and replaces the new in the debug version with the new one. The new one records the file name and code line when new is called. after running, you can see the following results:

Detected memory leaks!
Dumping objects->
D: \ code \ consoletest. 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. Let's take a look at the following code:

Int _ tmain (INT argc, _ tchar * argv [])
{
Int * P = new int;
_ Crtdumpmemoryleaks;
Delete P;
Return 0;
}

After running, we can find that we have deleted the pointer, but it still reports Memory leakage. As you can imagine, Every time new is called, the program records the call internally, similar to an array record. If delete is used, it will be deleted from the array, _ crtdumpmemoryleaks prints the current status of the array.

Therefore, in addition to dumping out the memory information when necessary, the most important thing is to use _ crtdumpmemoryleaks when the program exits;

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

Furthermore, what if the program deletes the pointer in the class destructor? 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 <crtdbg. h>
# 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;
}

We can see that the Destructor are called only when the program exits, and the memory is clearly not leaked, but such a statement is still reported.

How can we improve it? Check for Memory leakage 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 <crtdbg. h>
# 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 [])
{
_ 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 is automatically called 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, it is often missed, and many people will not repair the program's external performance even if they find that the memory is leaked. How can developers proactively fix memory leaks? I remember that I used to work with people to write a program. My function parameters are required and cannot be blank. However, when others always pass null values, there is no way to verify the function parameters, give him assert, so that when the program runs, the assert will always pop up, the pressure of debugging the program will be annoying, and other programmers will get bored, and the problem will be changed, and the input parameters will be correct. So I think we should let Programmers take the initiative to do one thing. First, let them feel that doing this thing can reduce their burden and make their work easier. Well, let's do the same. When the program exits, the program prompts out when the memory leak is detected.

Check for Memory leakage version 4:

# Include "stdafx. H"
# Include <assert. h>
# 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
Void exit
{
Int I = _ crtdumpmemoryleaks;
Assert (I = 0 );
}
Int _ tmain (INT argc, _ tchar * argv [])
{
Atexit (exit );
Int * P = new int;
Return 0;
}

This version checks for Memory leakage when the program exits. If yes, a dialog box is displayed.

Atexit (exit); set to execute the exit function when the program exits. In the exit function, if memory leakage exists, _ crtdumpmemoryleaks will return a non-0 value and will be occupied by assert.

This version is ready for use. But we can also make some improvements, because to accurately detect all the memory leaks in the code, we need to # define…… in the code ...... Copy to all new files. It is impossible for every file to copy so much code, so we can extract it and put it in a file. For example, I put it in kdetectmemoryleak. h. The content of this 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 <stdlib. h>
# Include <crtdbg. h>
# Ifdef _ debug
# Define new debug_clientblock
# Endif

Then, kdetectmemoryleak. H is included in the general file of the project. For example, a project created with vs is included in stdafx. h. Or in a common. h file that I created myself, this file contains some common code that is used by almost all files.

 

<This article is reprinted to http://www.oschina.net/docs/article/11647>

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.