Confirm if there is a memory leak
We know that if the MFC program detects a memory leak, it will alert the memory leak in the debug window when exiting the program. For example:
Class Cmyapp:public CWINAPP
{
Public
BOOL initapplication ()
{
int* leak = new INT[10];
return TRUE;
}
};
The resulting memory leak reports are generally as follows:
Detected memory leaks!
Dumping objects
C:worktest.cpp (186): {#} normal block at 0x003c4410, + bytes long.
Data: < > CD CD CD CD CD CD CD CD CDs CD CD
Object dump complete.
That's good. The problem is, if we do not like MFC, then there is no way? Or do it yourself?
Oh, this is not necessary. In fact, MFC did not do it by itself. The work of memory leak detection is VC + + C Runtime library do. In other words, as long as you are VC + + programmers, can easily detect memory leaks. Let's give you a sample:
#include <crtdbg.h>
inline void Enablememleakcheck ()
{
_CrtSetDbgFlag (_CrtSetDbgFlag (_crtdbg_report_flag) | _crtdbg_leak_check_df);
}
void Main ()
{
Enablememleakcheck ();
int* leak = new INT[10];
}
Run (reminder: Do not press CTRL+F5, press F5), you will find that the resulting memory leak report is similar to MFC, but there are different details, as follows:
Detected memory leaks!
Dumping objects
{0x003c4410} normal block at bytes long.
Data: < > CD CD CD CD CD CD CD CD CDs CD CD
Object dump complete.
Why is it? Look underneath.
Locating memory leaks due to which sentence
You have found that the program has a memory leak. The problem now is that we need to find the source of the leak.
In general, we first determine which sentence caused the memory leak. In MFC, this is easy. You can double-click a memory leak to report the text, or press f4,ide in the Debug window to help you navigate to the place where you requested the memory block. For the above example, this sentence:
int* leak = new INT[10];
This is somewhat helpful for your analysis of memory leaks. In particular, if this new only corresponds to a delete (or if you omit the delete), this will quickly confirm the crux of the problem.
As we have seen earlier, when you do not use MFC, the resulting memory leak report is different from MFC, and you immediately find that pressing F4 does not work. So what did MFC do?
Actually not, let's simulate the things that MFC does. Look at the following example:
inline void Enablememleakcheck ()
{
_CrtSetDbgFlag (_CrtSetDbgFlag (_crtdbg_report_flag) | _crtdbg_leak_check_df);
}
#ifdef _DEBUG
#define NEW New (_normal_block, __file__, __line__)
#endif
void Main ()
{
Enablememleakcheck ();
int* leak = new INT[10];
}
To run the sample again, you are pleasantly surprised to find that there is no difference between the memory leak report and MFC.
Quickly find memory leaks
It is sometimes not enough to determine which line the memory leak occurs in. In particular, there is a case where multiple releases are corresponding to the same new. In the actual project, the following two kinds of situations are typical:
- The place where the object was created is a class factory (classfactory) pattern. Many or even all class instances are created by the same new one. For this, it is largely not helpful to navigate to the row where the new object is located.
- The COM object. We know that COM objects use reference count to maintain the life cycle. In other words, there is only one place where the object is new, but there are many places to release, and you have to exclude it.
So, what's the best way to quickly locate a memory leak?
Answer: Yes.
When the memory leaks are complicated, you can locate the memory leaks in the following ways. This is one of the most effective ways I personally think of a common memory leak tracking approach.
Let's look back at the memory leak report generated by crtdbg:
Detected memory leaks!
Dumping objects
C:worktest.cpp (186): {#} normal block at 0x003c4410, + bytes long.
Data: < > CD CD CD CD CD CD CD CD CDs CD CD
Object dump complete.
In addition to the file name and line number of the memory allocation statement that generated the memory leak, we noticed a more unfamiliar message:. What does this integer value mean?
In fact, it represents the first few memory allocation operations. As this example represents, the 52nd time a memory allocation operation has leaked. You may say, I only new once, how can it be the 52nd time? It is easy to understand that the other memory request operation is called during the initialization of C. :)
Is it possible that we let the program run to the 52nd memory allocation operation, automatically stop and enter the debug state? Fortunately, CRTDBG does provide such a function: Long _CrtSetBreakAlloc (long nallocid). We add it:
inline void Enablememleakcheck ()
{
_CrtSetDbgFlag (_CrtSetDbgFlag (_crtdbg_report_flag) | _crtdbg_leak_check_df);
}
#ifdef _DEBUG
#define NEW New (_normal_block, __file__, __line__)
#endif
void Main ()
{
Enablememleakcheck ();
_CrtSetBreakAlloc (52);
int* leak = new INT[10];
}
You find that the program runs to int* leak = new INT[10]; One sentence, automatically stops to enter the debug state. With a little bit of experience, you can see that the information you get is far more valuable than getting the file name and line number when the program exits. Because the report leaks the file name and the line number, you obtain only the static information, however _CrtSetBreakAlloc is restores the entire scene, you can pass on the function call stack analysis (I found many people are not accustomed to look at the function call stack, if you belong to this situation, I highly recommend you to fill this lesson, Because it is too important) and other online debugging techniques to analyze the causes of memory leaks. Typically, this method of analysis can find the perpetrator within 5 minutes.
Of course, _CrtSetBreakAlloc requires that your program execution process be reversible (the memory allocation order of multiple executions does not change). This hypothesis is set up in most cases. However, in the case of multithreading, this is sometimes difficult to guarantee.
Fastest speed to find memory leaks