Use boundschecker to detect memory leakage

Source: Internet
Author: User
Boundschecker uses a technology called code injection to intercept calls to functions that allocate and release memory. Simply put, when your Program When running, the boundschecker DLL is automatically loaded into the address space of the process (which can be implemented through the system-level hook), and then it modifies the function calls for memory allocation and release in the process, let these calls first be transferred to its Code And then execute the original code. Boundschecker does not need to modify Source code Or project configuration file, which makes it very simple and straightforward to use.

Here we use the malloc function as an example to intercept other functions in a similar way.

Functions to be intercepted may be in DLL or program code. For example, if the C-Runtime Library is statically linked, the code of the malloc function will be linked to the program. To intercept calls to such functions, boundschecker dynamically modifies the commands of these functions.

The following two pieces of assembly code, one without boundschecker intervention, and the other with boundschecker intervention:
126: _ cribd void * _ cdecl malloc (
127: size_t nsize
128 :)
129 :{

00403c10 push EBP
00403c11 mov EBP, esp
130: Return _ nh_malloc_dbg (nsize, _ newmode, _ normal_block, null, 0 );
00403c13 push 0
00403c15 push 0
00403c17 Push 1
00403c19 mov eax, [_ newmode (0042376c)]
00403c1e push eax
00403c1f mov ECx, dword ptr [nsize]
00403c22 push ECx
00403c23 call _ nh_malloc_dbg (00403c80)
00403c28 add ESP, 14 h
131:} The following Code involves boundschecker:
126: _ cribd void * _ cdecl malloc (
127: size_t nsize
128:)
129 :{

00403c10 JMP 01f41ec8
00403c15 push 0
00403c17 Push 1
00403c19 mov eax, [_ newmode (0042376c)]
00403c1e push eax
00403c1f mov ECx, dword ptr [nsize]
00403c22 push ECx
00403c23 call _ nh_malloc_dbg (00403c80)
00403c28 add ESP, 14 h
131 :}
After boundschecker intervened, the first three assembly commands of the malloc function were replaced with a JMP command. The original three commands were moved to the address 01f41ec8. After the program enters malloc, JMP goes to 01f41ec8 and the original three commands are executed, which is then the world of boundschecker. In general, it records the return address of the function (the return address of the function is on the stack, so it is easy to modify), and then points the return address to the boundschecker code, then jump to the original instruction of the malloc function, that is, in the location of 00403c15. When the malloc function ends, the return address is modified, and it is returned to the boundschecker Code. At this time, the boundschecker records the memory pointer allocated by malloc, then jump to the original return address.

If the memory allocation/release functions are in the DLL, boundschecker uses another method to intercept calls to these functions. Boundschecker modifies the program's dll import table to point the function address in the table to its own address for interception.

By intercepting these allocation and release functions, the boundschecker can record the lifecycle of allocated memory or resources. The next question is how it relates to the source code. That is to say, when the boundschecker detects a memory leak, how does it report the code allocation of this memory block. The answer is debug information ). When we compile a debug program, the compiler will record the correspondence between the source code and the binary code and put it in a separate file (. PDB) or directly linked to the target program. By directly reading the debugging information, you can obtain the file on which the source code of a memory is allocated and the line on which the source code is located. With code injection and debug information, the boundschecker can not only record the source code location of the call assignment function, but also record the call stack at the time of allocation and the source code location of the function on the call stack. This is very useful when using a class library like MFC. Here is an example:

Void showxitemmenu ()
{
...
Cmenu menu;

Menu. createpopupmenu ();
// Add menu items.
Menu. trackpropupmenu ();
...
}

Void showyitemmenu ()
{
...
Cmenu menu;
Menu. createpopupmenu ();
// Add menu items.
Menu. trackpropupmenu ();
Menu. Detach (); // This will cause hmenu leak
...
}

Bool cmenu: createpopupmenu ()
{
...
Hmenu = createpopupmenu ();
...
} When showyitemmenu () is called, we intentionally cause hmenu leakage. However, for boundschecker, the leaked hmenu is allocated in class cmenu: createpopupmenu. Assume that many of your programs use the createpopupmenu () function of cmenu, such as cmenu: createpopupmenu (). You still cannot determine the root cause of the problem, is createpopupmenu () used in showxitemmenu () or showyitemmenu (), or other places ()? With the call stack information, the problem is easy. Boundschecker reports the leaked hmenu information as follows:
Function
File
Line

Cmenu: createpopupmenu
E: \ 8168 \ vc98 \ MFC \ include \ afxwin1.inl
1009

Showyitemmenu
E: \ testmemleak \ mytest. cpp
100
Other function calls are omitted here.

In this way, we can easily find that the function that causes the problem is showyitemmenu (). When using a class library such as MFC for programming, most API calls are encapsulated in the class of the class library, with the call stack information, we can easily track the truly leaked code.

Recording the call stack information slows down the running of the program. By default, boundschecker does not record the call stack information. Follow these steps to enable the call stack logging option:

1. Open the menu: boundschecker | setting...

2. on the error detection page, select Custom in the list of error detection scheme.

3. Select pointer and leak error check in the combox of category.

4. Hook the report call stack check box

5. Click OK.

Based on code injection, boundschecker also provides API parameter verification and memory over run functions. These functions are very beneficial for program development. Because these contents do not belong to the topic of this article, we will not detail them here.

Although boundschecker is so powerful, it still seems pale in the face of Implicit Memory leakage. So let's take a look at how to use performance monitor to detect memory leaks.

Use performance monitor to detect memory leakage

During the design process, the NT kernel has added the system monitoring function, such as CPU usage, memory usage, and I/O operation frequency, applications can read these counters to understand the running status of the entire system or a process. Performance Monitor is such an application.

To detect memory leakage, we can monitor three counters of the Process object, namely, handle count, virutal bytes, and working set. Handle count records the number of handle opened by the process. Monitoring the counter helps us find whether the program has handle leakage; virtual bytes records the size of the virtual memory currently used by the process in the virtual address space. NT Memory Allocation adopts two steps. First, in this case, the operating system does not allocate physical memory, but retains a segment of address. Then, submit the space and the operating system will allocate physical memory. Therefore, virtual bytes is generally larger than the working set of the program. Monitoring virutal bytes helps us find some underlying system problems. The working set records the total amount of memory submitted by the operating system for the process, this value is closely related to the total amount of memory applied by the program. If the program has a memory leak, this value will continue to increase, but virtual bytes is a skip increase.

Monitoring these counters allows us to understand the memory usage of processes. If there is a leak, even implicit memory leakage, these counters will continue to increase. However, we know that there is a problem, but we do not know where it is, so we generally use performance monitor to verify whether there is a memory leak, and use boundschecker to locate and solve it.

When performance monitor displays a memory leak, but boundschecker cannot detect it, there are two possibilities: first, occasional Memory leakage. In this case, make sure that the running environment and operation method of the program are the same when Performance Monitor is used and boundschecker is used. Second, implicit memory leakage occurs. At this time, you need to review the program design, and then carefully study the counter value change chart recorded by performance monitor, analyze the relationship between the changes and the program running logic, and find some possible causes. This is a painful process, full of assumptions, conjecture, verification, and failure, but it is also an excellent opportunity to accumulate experience.

Summary

Memory leakage is a big and complex problem. Even if Java and. Net have a gabarge collection mechanism, there is a possibility of leakage, such as implicit memory leakage. Due to space limitations and capacity limitations, this article can only make a rough research on this topic. Other problems, such as multi-module leakage detection and how to analyze the memory usage during the running of the program, can be further studied. If you have any ideas, suggestions, or errors, please contact me.

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.