| Valgrind 3.3 - Advanced Debugging and Profiling for GNU/Linux applications by J. Seward, N. Nethercote, J. Weidendorfer and the Valgrind Development Team Paperback (6"x9"), 164 pages ISBN 0954612051 RRP £12.95 ($19.95) |
5.5.3 Putting it all together
Memcheck's checking machinery can be summarised as follows:
- Each byte in memory has 8 associated V (valid-value) bits, saying whether or not the byte has a defined value, and a single A (valid-address) bit, saying whether or not the program currently has the right to read/write that address.
- When memory is read or written, the relevant A bits are consulted. If they indicate an invalid address, Memcheck emits an Invalid read or Invalid write error.
- When memory is read into the CPU's registers, the relevant V bits are fetched from memory and stored in the simulated CPU. They are not consulted.
- When a register is written out to memory, the V bits for that register are written back to memory too.
- When values in CPU registers are used to generate a memory address, or to determine the outcome of a conditional branch, the V bits for those values are checked, and an error emitted if any of them are undefined.
- When values in CPU registers are used for any other purpose, Memcheck computes the V bits for the result, but does not check them.
- Once the V bits for a value in the CPU have been checked, they are then set to indicate validity. This avoids long chains of errors.
-
When values are loaded from memory, Memcheck checks the A bits
for that location and issues an illegal-address warning if needed.
In that case, the V bits loaded are forced to indicate Valid,
despite the location being invalid.
This apparently strange choice reduces the amount of confusing
information presented to the user. It avoids the unpleasant
phenomenon in which memory is read from a place which is both
unaddressable and contains invalid values, and, as a result, you get
not only an invalid-address (read/write) error, but also a
potentially large set of uninitialised-value errors, one for every
time the value is used.
There is a hazy boundary case to do with multi-byte loads from
addresses which are partially valid and partially invalid. See
details of the flag
--partial-loads-okfor details.
Memcheck intercepts calls to malloc, calloc, realloc, valloc, memalign, free, new, new[], delete and delete[]. The behaviour you get is:
- malloc/new/new[]: the returned memory is marked as addressable but not having valid values. This means you have to write to it before you can read it.
- calloc: returned memory is marked both addressable and valid, since calloc clears the area to zero.
- realloc: if the new size is larger than the old, the new section is addressable but invalid, as with malloc.
- If the new size is smaller, the dropped-off section is marked as unaddressable. You may only pass to realloc a pointer previously issued to you by malloc/calloc/realloc.
- free/delete/delete[]: you may only pass to these functions a pointer previously issued to you by the corresponding allocation function. Otherwise, Memcheck complains. If the pointer is indeed valid, Memcheck marks the entire area it points at as unaddressable, and places the block in the freed-blocks-queue. The aim is to defer as long as possible reallocation of this block. Until that happens, all attempts to access it will elicit an invalid-address error, as you would hope.
| ISBN 0954612051 | Valgrind 3.3 - Advanced Debugging and Profiling for GNU/Linux applications | See the print edition |