A brief talk on memory leakage and its detection tool __c++

Source: Internet
Author: User
Tags constant garbage collection
A memory leak is a common and troubling problem for a C + + programmer. Many techniques have been developed to deal with this problem, such as Smart pointer,garbage collection. Smart pointer technology is more mature, the STL already contains the class to support the smart pointer, but it does not seem to be widely used, and it does not solve all the problems; garbage collection technology has matured in Java, However, the development of the C + + domain is not smooth, although it is very early to think in C + + also joined the GC support. The real world is like this, as a C/s + + programmer, memory leaks is your heart forever pain. Fortunately, however, there are a number of tools that can help us verify the existence of the memory leak and find the code for the problem.

definition of memory leaks

In general we often say that the memory leak is the heap memory leakage. Heap memory is that the program is allocated from the heap, of any size (the size of the memory block can be determined during the program run), and the freed memory must be displayed after use. The application generally uses functions such as malloc,realloc,new to allocate a piece of memory from the heap, and after use, the program must be responsible for the corresponding call free or delete to release the memory block, otherwise, this piece of memory can not be reused, we say this memory leak. The following applet demonstrates a scenario in which heap memory leaks:
[CPP]View plain copy void MyFunction (int nsize) {char* p= new char[nsize]; if (!           Getstringfrom (P, nsize)) {MessageBox ("Error");        Return       }//using The string pointed by P;   ... delete P; }
When the function Getstringfrom () returns zero, the memory pointed to by the pointer P is not released. This is a common scenario where memory leaks occur. The program allocates memory at the entrance, releasing the memory at the exit, but the C function can exit anywhere, so that a memory leak occurs when there is no release of the memory that should be freed at an exit.
In a broad sense, memory leaks include not only the leak of heap memory, but also the leakage of system resources (resource leak), such as the kernel mentality Handle,gdi object,socket, interface, etc., fundamentally these objects allocated by the operating system also consume memory, Leakage of these objects can eventually result in memory leaks. Also, some objects consume kernel-mindset memory, which can cause the entire operating system to become unstable when the objects are compromised. In contrast, system resource leaks are more severe than heap memory leaks.

The leakage of GDI object is a common resource leak:
[CPP]View plain copy void Cmyview::onpaint (cdc* pDC) {CBitmap bmp;       cbitmap* poldbmp; Bmp.       LoadBitmap (idb_mybmp);       Poldbmp = Pdc->selectobject (&bmp);       ... if (something ()) {return;       } pdc->selectobject (Poldbmp);   Return }
When the function something () returns Non-zero, the program does not select the Poldbmp back into the PDC before exiting, which causes the Hbitmap object that poldbmp points to leak. This program, if run for a long time, may cause the entire system to spend screen. This problem is more easily exposed under Win9x because the Win9x GDI heap is much smaller than Win2K or NT.

How the memory leaks occur:

In the manner in which they occur, memory leaks can be categorized into 4 categories:

1. Frequent memory leaks. The code that has a memory leak is executed multiple times, causing a memory leak each time it is executed. For example, if the something () function always returns True, then the Hbitmap object that poldbmp points to always leaks. 2. Accidental memory leaks. The code that occurs with a memory leak only occurs under certain circumstances or procedures. For example, if the something () function returns True only in a particular environment, then the Hbitmap object that poldbmp points to does not always leak. The frequent and incidental are relative. For a given environment, the occasional may become a frequent occurrence. So test environments and test methods are critical to detecting memory leaks.
3. Disposable memory leak. The code that has a memory leak is executed only once, or because of an algorithm flaw, there will always be a single and one memory leak. For example, allocating memory in the constructor of a class does not release the memory in the destructor, but because this class is a singleton, the memory leak occurs only once. Another example:
[CPP]View plain copy char* g_lpszfilename = NULL;       void Setfilename (const char* lpcszfilename) {if (g_lpszfilename) {free (g_lpszfilename);   } g_lpszfilename = StrDup (lpcszfilename); }
If the program does not release the G_lpszfilename point string at the end of the process, even if you call Setfilename () multiple times, there will always be a chunk of memory, and only one piece of memory will leak.
4. An implicit memory leak. The program keeps allocating memory while it is running, but it does not release memory until the end. Strictly speaking, there is no memory leak, because the final program frees up all of the requested memory. But for a server program, it can take days, weeks, or months to run out of memory, which may result in the eventual exhaustion of all of the system's memory. So, we call this kind of memory leak as an implicit memory leak. Give an example:
[CPP] View plain copy class connection   {   public:        Connection ( socket s);       ~connection ();        ...   private:       SOCKET _socket;        ...  };      class connectionmanager   {    public:       connectionmanager () {}       ~ ConnectionManager ()        {            std::list::iterator it;           for ( it  = _connlist.begin ()  it != _connlist.end (); ++it )             {                d elete  (*it);           }            _connlist.clear ();       }        void onclientconnected ( SOCKET s )        {            connection* p = new connection (s);            _connlist.push_back (p);        }       void onclientdisconnected ( connection* pconn  )        {           _ Connlist.remove ( pconn );           delete  pconn;       }   private:       std::list  _connlist;  };  
Assuming that the server does not call the onclientdisconnected () function after the client disconnects from the server side, the connection object representing that connection will not be deleted in time (when the server program exits, All connection objects are deleted in the ConnectionManager destructor. An implicit memory leak occurs when a continuous connection is established and disconnected.

From the user's point of view of the program, the memory leak itself will not produce any harm, as a general user, do not feel the existence of memory leaks. What really harms is the accumulation of memory leaks, which ultimately consumes all the memory of the system. In this sense, a one-time memory leak is harmless because it does not accumulate, and the implicit memory leak is very harmful because it is more difficult to detect than frequent and accidental memory leaks.


Detecting Memory leaksThe key to detecting a memory leak is to be able to intercept calls to the function that allocates and frees memory. By intercepting these two functions, we can track the life cycle of each piece of memory, for example, each time a piece of memory is successfully allocated, the pointer is added to a global list, and every time a piece of memory is released, its pointer is removed from the list. Thus, when the program is finished, the remaining pointers in the list point to the memory that is not freed. This is just a simple description of the basic principle of detecting memory leaks, and detailed algorithms can be found in Steve Maguire's <<writing Solid code>>.

If you want to detect heap memory leakage, then need to intercept the Malloc/realloc/free and New/delete on it (in fact, New/delete is also the end of the Malloc/free, so as long as the interception of the previous group can). For other leaks, a similar method can be used to intercept the corresponding allocation and release functions. For example, to detect BSTR leakage, you need to intercept sysallocstring/sysfreestring, to detect hmenu leakage, you need to intercept createmenu/destroymenu. (Some of the resource allocation function has more than one release function, for example, SysAllocStringLen can also be used to allocate BSTR, then need to intercept multiple allocation functions)

In the Windows platform, detection of memory leaks tools commonly used in three, MS c-runtime library built detection function; External detection tools, such as, Purify,boundschecker, etc. using Windows NT self-performance Monitor. These three tools have their advantages and disadvantages, MS C-runtime Library, although the function is weaker than the plug-in tools, but it is free; Performance Monitor does not have the code to indicate the problem, but it can detect the existence of an implicit memory leak, This is where the other two types of tools are powerless.

Below we discuss in detail these three kinds of detection tools:
A method for detecting memory leakage under VC
Applications developed with MFC are automatically added to the memory leak detection code when compiled in debug version mode. At the end of the program, if a memory leak occurs, the Debug window displays information about all the memory blocks that are leaking, and the following two lines display information about a leaked block of memory:

E:\TestMemLeak\TestDlg.cpp: {n} normal block at 0x00881710 bytes long.
Data: <abcdefghijklmnop> the 6A 6B 6C 6D 6E 6F 70

The first line shows that the memory block is allocated by the TestDlg.cpp file, the 70th line of code, the address is in 0x00881710, the size is 200 bytes, and {59} refers to the Request order for calling the memory allocation function, which can be seen in MSDN for more information. Help with Crtsetbreakalloc (). The second line shows the contents of the first 16 bytes of the memory block, which is shown in ASCII, followed by a 16-way display.

Generally, we all mistakenly think that these memory leak detection function is provided by MFC, but it is not. MFC only encapsulates and utilizes the debug Function of the MS C-runtime Library. Non-MFC programs can also take advantage of the debug function of Ms C-runtime Library to add memory leak detection capabilities. The MS C-runtime Library has built a memory leak detection function when implementing functions such as Malloc/free,strdup.


Take a look at the project generated by the MFC Application Wizard, which has a macro definition in the head of each CPP file:

#ifdef _DEBUG
#define NEW Debug_new
#undef This_file
static char this_file[] = __file__;
#endif

With this definition, when you compile the debug version, all new files that appear in this CPP file are replaced with Debug_new. So what is Debug_new? Debug_new is also a macro, and the following excerpt from the afx.h,1632 line

#define DEBUG_NEW NEW (this_file, __line__) so if you have one line of code:

char* p = new char[200]; The macro substitution becomes:
char* p = new (This_file, __line__) char[200];


According to C + + standards, for the above new use method, the compiler will look for the definition of operator new:void* operator new (size_t, LPCSTR, int)
We found one of these operator new implementations in the Afxmem.cpp 63 line.
[CPP]View Plain copy void* afx_cdecl operator new (size_t nsize, lpcstr lpszfilename, int nline) {return:: operator new   (Nsize, _normal_block, lpszFileName, nline); } void* __cdecl operator new (size_t nsize, int ntype, LPCSTR lpszfilename, int nline) {... pResult = _       malloc_dbg (nsize, Ntype, lpszFileName, nline);       if (PResult!= NULL) return pResult; ...   }
The second operator new function is relatively long, for the sake of simplicity, I have only excerpted the part. It is clear that the final memory allocation is implemented through the _MALLOC_DBG function, which belongs to the debug function of the MS C-runtime Library. This function requires not only the size of the incoming memory, but also the filename and line number two parameters. The file name and line number are used to record which section of code this allocation is caused by. If the inside of this piece is not released before the end of the program, then the information will be exported to the Debug window.

Here, by the way, This_file,__file and __line__. Both __file__ and __line__ are compiler-defined macros. When encountering __file__, the compiler replaces __file__ with a string that is the pathname of the file currently being compiled. When the __line__ is encountered, the compiler replaces the __line__ with a number, which is the line number of the current line of code. Instead of using __file__ directly in the definition of debug_new, this_file is used to reduce the size of the target file. Suppose that there are 100 new in a CPP file, and if you use __file__ directly, the compiler produces 100 constant strings, which are all chiselled/span>cpp file pathname, apparently very redundant. If you use This_file, the compiler produces only a constant string, and the 100 new calls use pointers to constant strings.

Looking again at the project generated by the MFC Application Wizard, we will find that only the new mapping in the CPP file, if you use the malloc function to allocate memory directly in the program, the file name and line number of the call malloc will not be recorded. If this memory is leaking, the MS C-runtime Library can still detect it, but when the information for this block of memory is exported, the file name and line number assigned to it are not included.

To turn on memory leak detection in non-MFC programs is very easy, you just add the following lines to the entrance of the program:

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.