Introduction to Memcheck

The Valgrind tool suite provides a number of debugging and profiling tools that help you make your programs faster and more correct. The most popular of these tools is called Memcheck. It can detect many memory-related errors that are common in C and C++ programs and that can lead to crashes and unpredictable behaviour.

Memcheck inserts extra instrumentation code. Instrumentation refers to an ability to monitor or measure the level of a product's performance, to diagnose errors and to write trace information. Programmers implement instrumentation in the form of code instructions that monitor specific components in a system. When an application contains instrumentation code, it can be managed using a management tool. Instrumentation is necessary to review the performance of the application.

Memchek's extra instrumentation code keeps track of the validity (all unallocated memory starts as invalid or "undefined", until it is initialized into a deterministic state, possibly from other memory) and addressability (whether the memory address in question points to an allocated, non-freed memory block), stored in the so-called V bits and A bits, respectively. As data is moved around or manipulated, the instrumentation code keeps track of the A and V bits so they are always correct on a single-bit level.

 In addition, Memcheck replaces the standard C memory allocator with its own implementation, which also includes memory guards around all allocated blocks (with the A bits set to "invalid"). This feature enables Memcheck to detect off-by-one errors where a program reads or writes outside an allocated block by a small amount. 

Memcheck can detect the following problems that are common in C and C++ programs.
  • Accessing memory you shouldn’t, e.g. overrunning and underrunning heap blocks, overrunning the top of the stack, and accessing memory after it has been freed.
  • Using undefined values, i.e. values that have not been initialised, or that have been derived from other undefined values.
  • Incorrect freeing of heap memory, such as double-freeing heap blocks, or mismatched use of malloc/new/new[] versus free/delete/delete[]
  • Overlapping src and dst pointers in memcpy and related functions.
  • Memory leaks.
Problems like these can be difficult to find by other means, often remaining undetected for long periods, then causing occasional, difficult-to-diagnose crashes