A look into the real-world applications built on top of C and C++ displays diverse applications like OS, new languages, computational-platforms, embedded-systems, graphics games and browsers and the like. These applications are being supported in most of the targeted devices and are providing great business value and performance.
Recently we came across a performance issue in our network test device wherein the device performance was comparatively getting slower when a particular module of the application was being load tested. We also observed unexpected application behaviors and application termination as well and while debugging the code, it was identified that the root cause was a memory leak. Fixing the memory leak resulted in better performance.
A memory leak is the loss of available memory when a program fails to return memory that it has obtained for temporary use. For a program that is frequently opened or for the one that runs continuously, even a very small memory leak can eventually cause the program to terminate. A memory leak is the result of a programming bug and hence it is very important to test it during the development phase. Therefore it is important to start considering memory leak testing as part of QA testing to avoid any such memory-related issues, which could cause production disruptions.
This blog post sheds light on performing a memory leak test using Valgrind and the other various options that are available in the market.
Memory Leak Testing Tools
As stated earlier, it is very important to conduct memory leak tests to ensure that there are no disruptions in the production. Some of the memory leak testing tools that are available in the market are as follows:
- GlowCode: This tool is used to find memory leaks in the running applications written in C++, C# or .NET compliant language. While the application runs, this tool shows the duration, frequency, and use of function calls, and finds the methods that consume more time.
- AQTime by Smartbear: This is a proprietary tool by Smartbear that supports Delphi, C#, C++, .NET, Java, etc. It can identify performance issues and memory leaks. It analyses function call order and resource usage.
- BoundsChecker: BoundsChecker is an API call validation and memory checking tool used for C++ software development with Microsoft Visual C++. This became part of a larger tool suite, Dev Partner Studio.
- MemCheck by Valgrind: The instrumentation framework for building dynamic analysis tools is called Valgrind. There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile our programs in detail.
- Deleaker: This is a standalone memory leak detection tool and is also used as the Visual C++ extension. This tool detects memory leaks in heap and virtual memory as well and easily integrates with any IDE.
Considering Robustness, Usage, Distribution, Features, Docs, Error Message reporting, Bugs finding and the like, Valgrind is one of the best solutions among this. Valgrind offers your application a virtual processor. They are passed to the Valgrind tool plugin before your application instructions are processed. The best part about this is that you don’t have to change or re-connect your software to run it.
Valgrind – The Ultimate Tool for Memory Leak Detection, Memory Debugging & Profiling
Valgrind was designed to be a free memory debugging tool for Linux x86, but it has evolved to be a generic framework for creating dynamic analysis tools. It’s a virtual machine using just-in-time compilation techniques, including dynamic recompilation. While using Valgrind, the program will not run directly on the host processor. Instead, Valgrind first translates the program into a temporary form called Intermediate Representation. The Valgrind can do all the transformations on the program once it is converted. And this will be converted back into machine code (recompiles) and the processor can run it.
Platforms Supported by Valgrind
The various platforms that are supported by Valgrind are:
- PPC32/Linux, PPC64/Linux, and PPC64LE/Linux.
- MIPS32/Linux, MIPS64/Linux.
- X86/Solaris, AMD64/Solaris, X86/illumos, AMD64/illumos.
- X86/Darwin (10.10, 10.11), AMD64/Darwin (10.10, 10.11.
- ARM/Android, ARM64/Android, MIPS32/Android, X86/Android.
- Memcheck: This is the main module that provides memory leak detection. This module also has the capability of finding other errors of work with memory and read/write behind memory blocks.
- Cachegrind: This tool can analyze the execution of code, find out processor cache misses and code branching. This will be collected for all programs, separate functions, and lines of code.
- Callgrind: This is similar to the cachegrind module and analyses functions calls using almost the same methods. This allows you to prepare the tree of functions calls, and analyze performance.
- Massif: This tool allows us to analyze memory consumption in various parts of Application program.
- Helgrind: This is used to track the presence of different synchronization errors in programs, which use POSIX Threads.
MemCheck is the most popular of these tools. It detects those memory-related errors that are common in C and C++ programs and can lead to crashes and unpredictable behavior. It can detect the following scenarios:
- Uninitialized memory
- Reading/writing memory a freed memory
- Reading/writing after malloc’d blocks
- Reading/writing inappropriate areas on the stack
- Memory leaks
- Mismatched use of malloc/new/new vs free/delete/delete
- Overlapping source and destination pointers in related functions
Given below is a visual representation of Memcheck in Valgrind:
Click here to find out how How to Perform Memory Leak Test Leveraging Valgrind
Valgrind in Android
Valgrind can be used for the memory leak test in android applications having JNI Library. Native functions are implemented in separate .c or .cpp files in the JNI framework. (C++ provides a slightly simpler interface with JNI.) When the JVM invokes the function, it passes a JNIEnv pointer, a jobject pointer, and any Java arguments declared by the Java method. If you write a JNI library, then consider Valgrind to ensure that your library does not leak memory.
Limitations of Valgrind
Despite its various advantages, Valgrind does have its own set of limitations. A considerable amount of performance is lost during the transformations that happen while Valgrind starts to run. Usually, the code runs with Valgrind and the “none” tool runs at 1/4 to 1/5 of the speed of the normal program. The inability to detect all cases of bounds errors in the use of static or stack-allocated data is an important limitation of Memcheck.
As mentioned, Valgrind can trace memory leak issues and let us know the areas that need to be resolved to avoid such situations. Since the background actions in Valgrind are a bit time consuming, this will slow down the test performance. Even though Valgrind consumes a lot of memory while executing with the test app, this is a good tool to detect memory leaks. So it is important to start adding memory leak tests to our scope wherever possible and save expensive time and effort by identifying the issues early in the test cycle, rather than taking a chance to see if this happens in production.
Senior Software Engineer -Testing, RapidValue