Leaks are gone... or not?
When we run our last build with valgrind, everything looks fine. Check our valgrind log below:
==901== Memcheck, a memory error detector
==901== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==901== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==901== Command: ./lights.bin
==901== Parent PID: 900
==901==
==901==
==901== HEAP SUMMARY:
==901== in use at exit: 0 bytes in 0 blocks
==901== total heap usage: 89 allocs, 89 frees, 1,974 bytes allocated
==901==
==901== All heap blocks were freed -- no leaks are possible
==901==
==901== For counts of detected and suppressed errors, rerun with: -v
==901== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
However, remember that we don't call Application::render() yet. And valgrind can only detect leaks from executed code. When requested, Display::quitRequest() function always returns true, so render function cannot be executed. So, let's tweak Display::quitRequest() function a bit; so it returns false for a number of times before it finally returns true.
bool Display::quitRequest() {
// TODO return quit request.
static int count=1000;
bool quit = false;
count--;
if (count < 0) {
quit = true;
}
return quit;
}
When you compile with this changes, and run with grind.sh, we get following log file:
==4720== Memcheck, a memory error detector
==4720== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==4720== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==4720== Command: ./lights.bin
==4720== Parent PID: 4719
==4720==
==4720==
==4720== HEAP SUMMARY:
==4720== in use at exit: 6,712 bytes in 250 blocks
==4720== total heap usage: 526 allocs, 276 frees, 11,254 bytes allocated
==4720==
==4720== 1,224 (360 direct, 864 indirect) bytes in 9 blocks are definitely lost in loss record 6 of 8
==4720== at 0x4C2C154: operator new(unsigned long) (vg_replace_malloc.c:298)
==4720== by 0x400F07: Application::setUpObjects() (Application.cpp:89)
==4720== by 0x400973: main (Main.cpp:7)
==4720==
==4720== 5,488 (2,352 direct, 3,136 indirect) bytes in 98 blocks are definitely lost in loss record 8 of 8
==4720== at 0x4C2C154: operator new(unsigned long) (vg_replace_malloc.c:298)
==4720== by 0x40483E: Edge::castShadow(Light*) (Edge.cpp:42)
==4720== by 0x400CED: Application::render() (Application.cpp:50)
==4720== by 0x40098D: main (Main.cpp:12)
==4720==
==4720== LEAK SUMMARY:
==4720== definitely lost: 2,712 bytes in 107 blocks
==4720== indirectly lost: 4,000 bytes in 143 blocks
==4720== possibly lost: 0 bytes in 0 blocks
==4720== still reachable: 0 bytes in 0 blocks
==4720== suppressed: 0 bytes in 0 blocks
==4720==
==4720== For counts of detected and suppressed errors, rerun with: -v
==4720== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
New leaks appear. Valgrind can only detect memory leaks in executed program sections. Naturally, if we have code sections that is not executed, all possible errors & leaks in them will stay dormant.
Coverage and Testing
So, how can be assure that all code sections in our program will be executed? Here comes Coverage Analysis and Testing topics.
We can use coverage analysis tools to detect non-executed code lines. Then we can force them to execute by testing techniques.
lcov
We finish this post by explaining how to use lcov, a coverage analysis tool for linux platforms. We will use lcov to understand what causes our existing memory leaks.
First thing we do is to install lcov:
$ sudo apt-get install lcov
Then we update our makefile to generate data needed by lcov tool:
...
FLAGS=-g -Wall -Wextra -Werror -Wfatal-errors
FLAGS+=-O0 -coverage
...
We just added to switches to compiler & linker flags. When we build with these options, additional files with extension .gcno is generated. Now we should run our application to collect data.
$ ./lights.bin
After this step you see more additional files (with .gcda extension) appears in our project folder. We can now proceed with report generation. For this, we run following command in our project folder:
$ lcov -o report.info -c -d .
Generated report.info file is in text format, however it is hard to read and interpret. Therefore, we generate a much more readable html format for coverage information. For this purpose, we run following command:
$ genhtml -o report --no-branch-coverage report.info
At the end of this last step, we have a folder named report which contains coverage analysis for our application. Run following:
$ cd report
$ google-chrome ./index.html
You can find a link to generated report here. We will examine contents of this report in next post.