| 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.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 addresspoolas the anchor address for a memory pool. It also provides a sizerzB, specifying how large the redzones placed around chunks allocated from the pool should be. Finally, it provides anis_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 asize-byte chunk has been allocated ataddr, and associates the chunk with the specifiedpool. If the pool was created with nonzerorzBredzones, Memcheck will mark therzBbytes before and after the chunk as NOACCESS. If the pool was created with theis_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 ataddrshould no longer be considered allocated. Memcheck will mark the chunk associated withaddras NOACCESS, and delete its record of the chunk's existence. -
VALGRIND_MEMPOOL_TRIM(pool, addr, size): This request “trims” the chunks associated withpool. The request only operates on chunks associated withpool. 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_MEMPOOL_FREE.
-
VALGRIND_MOVE_MEMPOOL(poolA, poolB): This request informs Memcheck that the pool previously anchored at addresspoolAhas moved to anchor addresspoolB. This is a rare request, typically only needed if yourealloc()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 addressaddrAwithinpoolhas 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 yourealloc()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 addresspool. 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 |