My First Post      My Facebook Profile      My MeOnShow Profile      W3LC Facebook Page      Learners Consortium Group      Job Portal      Shopping


Monday, February 20, 2012

Analysis of Valgrind “Still-reachable” memory leak

Valgrind, on Linux and FreeBSD etc, reports “Still reachable” in Memory Leaks section using the memcheck or mc tool. What is REAL Memory Leak and why some leaks are called False Positives?

Many programs use the C++ STL and string classes. Valgrind, at times (rather too often ;) ) reports “still reachable” memory leaks involving these classes at the exit of the program. Ideally, there should be no such occurrence, so what should be done.
To take this article further, one thing that has to be kept in mind that it may not be a bug. Every tool has its own False positives, and Valgrind is no exception. And in this case, this is not even a False positive. It just indicates a possible issue, which may be just intended by the programmer.

This article can be regarded as an extension to the memory leak tutorial on Valgrind. It will make the Software Quality Assurance Engineers and developers more confident on their releases. Here I discuss the Still Reachable part of the Valgrind memcheck report

Let us assume that you started a Valgrind with its memcheck tool, and Valgrind initial logs say as following:
==12078== Memcheck, a memory error detector
==12078== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==12078== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==12078== Command: ./mohd-anwar-faiz-test-tool --helloWorld /targetFolder/
==12078== Parent PID: 1287
--12078-- Valgrind options:
--12078-- --tool=memcheck
--12078-- --leak-check=yes
--12078-- --show-reachable=yes
--12078-- --num-callers=20
--12078-- --track-fds=yes
--12078-- -v
--12078-- --log-file=/perforce/work/mohd-anwar-faiz-test-tool.txt
--12078-- Contents of /proc/version:
--12078-- Arch and hwcaps: AMD64, amd64-sse3-cx16

…, and the processing goes on.

So, this logs simply tells you about the options you used. And, this gives you the confidence that memory leaks will be catched.

Now, let us see what actually a memory leak is in this context. During my stint with Software Product Development companies like Adobe and Symantec, I have really discovered more than one definition to the concept of a "memory leak".

The first says that a "memory leak" happens when, " Some memory that has been allocated is not subsequently freed before the termination of the program." However, I have seen programmers arguing (And that is why probably we hear terms like False Positives. Voila!), that certain memory leaks that fall into above category do not actually pose any threat, and therefore must not be regarded as real "memory leaks". They are NOT REAL “memory leaks”.

Another definition says that a "memory leak" happens when, "Some memory was allocated but that cannot be subsequently freed. This situation may arise if the program no longer holds any pointers to the allocated memory." That is, memory cannot be freed since you no longer have any pointers to that block. Such a condition is then a REAL "memory leak".

Now coming to Valgrind, it uses the latter definition for the term "memory leak". This is the type of leak which may potentially cause real heap depletion, particularly for long lived processes. These can be surfaced by persistence tests. And, tools like Valgrind, AppVerifier, Fortify etc come into roles.

Let us assume that your application gave result as follows:

==12078== LEAK SUMMARY:
==12078== definitely lost: 0 bytes in 0 blocks
==12078== indirectly lost: 0 bytes in 0 blocks
==12078== possibly lost: 0 bytes in 0 blocks
==12078== still reachable: 6,720 bytes in 26 blocks
==12078== suppressed: 0 bytes in 0 blocks

So now, the above sample clearly tells that there are no memory leaks. But, still-reachable section shows some counts. Now here, it must be taken into consideration that the "still reachable" category in the Valgrind's leak report refers to allocations that fall into the category of first definition. It is true that these reported blocks were not freed; But these could have been freed. And that is what is the literal meaning of the term ‘STILL REACHABLE’. So, may be it was intentionally left by the programmer, because in any case the program during all its execution was keeping track of these pointers.

I have been in touch with my former colleague at Tata Consultancy Services over this issue (Thanks to *SO*), and was issued the same advice. Later I googled and found similar conclusion from the Valgrind FAQ document itself. As seen from documents on Valgrind official website itself Valgrind Official Documentation Page, these situations might arise and there is not much to worry about them. Read below, an snippet from their web pages itself:
Using GCC, you can force the STL to use malloc and to free memory as soon as possible by globally disabling memory caching. Beware! Doing so will probably slow down your program, sometimes drastically.
• With GCC 2.91, 2.95, 3.0 and 3.1, compile all source using the STL with -D__USE_MALLOC. Beware! This was removed from GCC starting with version 3.3.
• With GCC 3.2.2 and later, you should export the environment variable GLIBCPP_FORCE_NEW before running your program.
• With GCC 3.4 and later, that variable has changed name to GLIBCXX_FORCE_NEW.
There are other ways to disable memory pooling: using the malloc_alloc template with your objects (not portable, but should work for GCC) or even writing your own memory allocators. But all this goes beyond the scope of this FAQ. Start by reading if you absolutely want to do that. But beware: allocators belong to the more messy parts of the STL and people went to great lengths to make the STL portable across platforms. Chances are good that your solution will work on your platform, but not on others.

So, what I conclude and do practice is that, there is no need to worry about "still reachable" memory leaks in Valgrind. They do not pose threats as the REAL memory leaks do. Practically these NON-REAL memory leaks have no potential for heap exhaustion. You can revisit the code for gaining more confidence, if your project cycle permits that much time (which I know is rare!! :) ). There is not much need to worry for these still reachable pointers. These allocations were done and the references were kept throughout the process execution cycle. And in the end, the operating system will reclaim these allocated memory after the process termination.

That is it for the day.
-Mohd Anwar Jamal Faiz
Poet and Creative Writer. Software Engineering is both my job and passion. I love what I do!!

Valgrind Version Used: Valgrind-3.6.1 and LibVEX;
Platform Used: FreeBSD 64 bit, Linux, Solaris

To know more about me cheack: Anwar Faiz on MeOnShow

No comments:

Post a Comment