Valgrind comprises a bunch of very useful tools for detecting problems with your programs. I first came across it a couple of years back and find it to be excellent. In particular I use its memory profiler, which helps you catch errors such as memory leaks and invalid accesses. In my experience these types of errors sometimes indicate logic errors, not just areas where you’ve forgotten to free some previously allocated memory — which is another reason why it is such a great tool.
I usually invoke Valgrind in a straightforward manner:
valgrind --leak-check=full --show-reachable=yes
These two options generally show me all I need to know.
A while back I wrote a ~2,000 line parsing library in C. Nothing too complex — it parses a configuration file on disk, stores and modifies the details in memory, only writing back to disk when explicitly told to do so by the library client. It used plenty of dynamic memory, and Valgrind was an enormous help when it came to ensuring its correctness, The library is a critical piece of a production system so it needed to be right. And in the two years since it was released there have only been 3 very small changes to the source.
Testing with exec
Sometimes the program you wish to test is actually controlled by other programs on your system, and you would like to Valgrind your program in that environment. Programs stored in /etc/init.d are an example of this.
The question becomes how does one insert Valgrind between the controlling program, and the one you wish to test? A first attempt could be to replace the program you wish to test with a bash script like this:
valgrind --leak-check=full --show-reachable=yes --log-file=/var/tmp/vg_log
This way the system launches this script when it wishes to launch your program. The script in turn launches your program. The problem with this approach is that the original bash process is between the launching program and your program. Any signals sent by the system will not reach your program — and how your system responds to signals may be an important part of your testing.
How can you address this issue? You can use the exec call. The script now looks like this:
exec valgrind --leak-check=full --show-reachable=yes --log-file=/var/tmp/vg_log $YOUR_PROGRAM-RENAMED-TO-SOMETHING-ELSE
I never really appreciated the power of exec until I used it in this manner. exec causes the bash process to be replaced by the Valgrind process, and Valgrind always passes on signals it receives to the test program. The result is a perfect testing environment.