4. A Closer View

4.1. Why Valgrind?

As said above, memory management is prone to errors that are too hard to detect. Common errors may be listed as:

  1. Use of uninitialized memory

  2. Reading/writing memory after it has been freed

  3. Reading/writing off the end of malloc'd blocks

  4. Reading/writing inappropriate areas on the stack

  5. Memory leaks -- where pointers to malloc'd blocks are lost forever

  6. Mismatched use of malloc/new/new[] vs free/delete/delete[]

  7. Some misuses of the POSIX pthreads API

These errors usually lead to crashes.

This is a situation where we need Valgrind. Valgrind works directly with the executables, with no need to recompile, relink or modify the program to be checked. Valgrind decides whether the program should be modified to avoid memory leak, and also points out the spots of "leak."

Valgrind simulates every single instruction your program executes. For this reason, Valgrind finds errors not only in your application but also in all supporting dynamically-linked (.so-format) libraries, including the GNU C library, the X client libraries, Qt if you work with KDE, and so on. That often includes libraries, for example the GNU C library, which may contain memory access violations.

4.2. Usage

4.2.3. Types of Errors with Examples

Valgrind can only really detect two types of errors: use of illegal address and use of undefined values. Nevertheless, this is enough to discover all sorts of memory management problems in a program. Some common errors are given below.

4.2.3.4. Mismatched Use of Functions

In C++ you can allocate and free memory using more than one function, but the following rules must be followed:

Sample program:


#include <stdlib.h>
int main()
{
        int *p, i;
        p = ( int* ) malloc(10*sizeof(int));
        for(i = 0;i < 10;i++)
                p[i] = i;
        delete(p);                /* Error: function mismatch */
        return 0;
}

Output by valgrind is:


             ==1066== ERROR SUMMARY: 1 errors from 1 contexts (suppressed:
0 from 0)
             ==1066== malloc/free: in use at exit: 0 bytes in 0 blocks.
             ==1066== malloc/free: 1 allocs, 1 frees, 40 bytes allocated.
             ==1066== For a detailed leak analysis,  rerun with:
--leak-check=yes
             ==1066== For counts of detected errors, rerun with: -v

>From the above "ERROR SUMMARY" it is clear that there is 0 bytes in 0 blocks in use at exit, which means that the malloc'd have been freed by delete. Therefore this is not a problem in Linux, but this program may crash on some other platform.

4.3. Limitations and Dependencies of Valgrind.

No software is free from limitations. The same is the case of Valgrind, however most programs work fine. The limitations are listed below.

  1. Program runs 25 to 50 times slower.

  2. Increased memory consumption.

  3. Highly optimized code (compiled with -O1, -O2 options ) may sometimes cheat Valgrind.

  4. Valgrind relies on dynamic linking mechanism.

Valgrind is closely tied to details of the CPU, operating system and to a less extent, compiler and basic C libraries. Presently Valgrind works only on the Linux platform (kernels 2.2.X or 2.4.X) on x86s. Glibc 2.1.X or 2.2.X is also required for Valgrind.