|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
RRP £12.95 ($19.95)
5.7 Memory Pools: describing and working with custom allocators
Some programs use custom memory allocators, often for performance reasons. Left to itself, Memcheck is unable to “understand” the behaviour of custom allocation schemes and so may miss errors and leaks in your program. What this section describes is a way to give Memcheck enough of a description of your custom allocator that it can make at least some sense of what is happening.
There are many different sorts of custom allocator, so Memcheck attempts to reason about them using a loose, abstract model. We use the following terminology when describing custom allocation systems:
- Custom allocation involves a set of independent “memory pools”.
- Memcheck's notion of a a memory pool consists of a single “anchor address” and a set of non-overlapping “chunks” associated with the anchor address.
- Typically a pool's anchor address is the address of a book-keeping “header” structure.
- Typically the pool's chunks are drawn from a contiguous “superblock” acquired through the system malloc() or mmap().
Keep in mind that the last two points above say “typically”: the Valgrind mempool client request API is intentionally vague about the exact structure of a mempool. There is no specific mention made of headers or superblocks. Nevertheless, the following picture may help elucidate the intention of the terms in the API:
"pool" (anchor address) | v +--------+---+ | header | o | +--------+-|-+ | v superblock +------+---+--------------+---+------------------+ | |rzB| allocation |rzB| | +------+---+--------------+---+------------------+ ^ ^ | | "addr" "addr"+"size"
Note that the header and the superblock may be contiguous or discontiguous, and there may be multiple superblocks associated with a single header; such variations are opaque to Memcheck. The API only requires that your allocation scheme can present sensible values of “pool”, “addr” and “size”.
Typically, before making client requests related to mempools, a client
program will have allocated such a header and superblock for their
mempool, and marked the superblock NOACCESS using the
VALGRIND_MAKE_MEM_NOACCESS client request.
When dealing with mempools, the goal is to maintain a particular invariant condition: that Memcheck believes the unallocated portions of the pool's superblock (including redzones) are NOACCESS. To maintain this invariant, the client program must ensure that the superblock starts out in that state; Memcheck cannot make it so, since Memcheck never explicitly learns about the superblock of a pool, only the allocated chunks within the pool.
Once the header and superblock for a pool are established and properly marked, there are a number of client requests programs can use to inform Memcheck about changes to the state of a mempool:
VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed): This request registers the address
poolas the anchor address for a memory pool. It also provides a size
rzB, specifying how large the redzones placed around chunks allocated from the pool should be. Finally, it provides an
is_zeroedflag that specifies whether the pool's chunks are zeroed (more precisely: defined) when allocated. Upon completion of this request, no chunks are associated with the pool. The request simply tells Memcheck that the pool exists, so that subsequent calls can refer to it as a pool.
VALGRIND_DESTROY_MEMPOOL(pool): This request tells Memcheck that a pool is being torn down. Memcheck then removes all records of chunks associated with the pool, as well as its record of the pool's existence. While destroying its records of a mempool, Memcheck resets the redzones of any live chunks in the pool to NOACCESS.
VALGRIND_MEMPOOL_ALLOC(pool, addr, size): This request informs Memcheck that a
size-byte chunk has been allocated at
addr, and associates the chunk with the specified
pool. If the pool was created with nonzero
rzBredzones, Memcheck will mark the
rzBbytes before and after the chunk as NOACCESS. If the pool was created with the
is_zeroedflag set, Memcheck will mark the chunk as DEFINED, otherwise Memcheck will mark the chunk as UNDEFINED.
VALGRIND_MEMPOOL_FREE(pool, addr): This request informs Memcheck that the chunk at
addrshould no longer be considered allocated. Memcheck will mark the chunk associated with
addras NOACCESS, and delete its record of the chunk's existence.
VALGRIND_MEMPOOL_TRIM(pool, addr, size): This request “trims” the chunks associated with
pool. The request only operates on chunks associated with
pool. Trimming is formally defined as:
- All chunks entirely inside the range [addr,addr+size) are preserved.
All chunks entirely outside the range [addr,addr+size) are
discarded, as though
VALGRIND_MEMPOOL_FREEwas called on them.
All other chunks must intersect with the range
[addr,addr+size); areas outside the intersection are marked as
NOACCESS, as though they had been independently freed with
VALGRIND_MOVE_MEMPOOL(poolA, poolB): This request informs Memcheck that the pool previously anchored at address
poolAhas moved to anchor address
poolB. This is a rare request, typically only needed if you
realloc()the header of a mempool. No memory-status bits are altered by this request.
VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size): This request informs Memcheck that the chunk previously allocated at address
poolhas been moved and/or resized, and should be changed to cover the region
[addrB,addrB+size). This is a rare request, typically only needed if you
realloc()a superblock or wish to extend a chunk without changing its memory-status bits. No memory-status bits are altered by this request.
VALGRIND_MEMPOOL_EXISTS(pool): This request informs the caller whether or not Memcheck is currently tracking a mempool at anchor address
pool. It evaluates to 1 when there is a mempool associated with that address, 0 otherwise. This is a rare request, only useful in circumstances when client code might have lost track of the set of active mempools.
|ISBN 0954612051||Valgrind 3.3 - Advanced Debugging and Profiling for GNU/Linux applications||See the print edition|