Developer Documentation

# Debugging Memory Allocation in APR

The allocation mechanism's within APR have a number of debugging modes that can be used to assist in finding memory problems. This document describes the modes available and gives instructions on activating them.

# Available debugging options

## Allocation Debugging - ALLOC_DEBUG

Debugging support: Define this to enable code which helps detect re-use of `free()`d memory and other such nonsense.

The theory is simple. The `FILL_BYTE` (`0xa5`) is written over all `malloc`'d memory as we receive it, and is written over everything that we free up during a `clear_pool`. We check that blocks on the free list always have the `FILL_BYTE` in them, and we check during `palloc()` that the bytes still have `FILL_BYTE` in them. If you ever see garbage URLs or whatnot containing lots of `0xa5`s then you know something used data that's been freed or uninitialized.

## Malloc Support - ALLOC_USE_MALLOC

If defined all allocations will be done with `malloc()` and `free()`d appropriately at the end.

This is intended to be used with something like Electric Fence or Purify to help detect memory problems. Note that if you're using efence then you should also add in `ALLOC_DEBUG`. But don't add in `ALLOC_DEBUG` if you're using Purify because `ALLOC_DEBUG` would hide all the uninitialized read errors that Purify can diagnose.

## Pool Debugging - POOL_DEBUG

This is intended to detect cases where the wrong pool is used when assigning data to an object in another pool.

In particular, it causes the `table_{set,add,merge}n` routines to check that their arguments are safe for the `apr_table_t` they're being placed in. It currently only works with the unix multiprocess model, but could be extended to others.

## Table Debugging - MAKE_TABLE_PROFILE

Provide diagnostic information about make_table() calls which are possibly too small.

This requires a recent gcc which supports `__builtin_return_address()`. The error_log output will be a message such as:

table_push: apr_table_t created by 0x804d874 hit limit of 10

Use `l *0x804d874` to find the source that corresponds to. It indicates that a `apr_table_t` allocated by a call at that address has possibly too small an initial `apr_table_t` size guess.

## Allocation Statistics - ALLOC_STATS

Provide some statistics on the cost of allocations.

This requires a bit of an understanding of how alloc.c works.

# Allowable Combinations

Not all the options outlined above can be activated at the same time. the following table gives more information.

| ALLOC DEBUG | ALLOC USE MALLOC | POOL DEBUG | MAKE TABLE PROFILE | ALLOC STATS
--- | --- | --- | --- | --- | ---
ALLOC DEBUG | - | No | Yes | Yes | Yes
ALLOC USE MALLOC | No | - | No | No | No
POOL DEBUG | Yes | No | - | Yes | Yes
MAKE TABLE PROFILE | Yes | No | Yes | - | Yes
ALLOC STATS | Yes | No | Yes | Yes | -

Additionally the debugging options are not suitable for multi-threaded versions of the server. When trying to debug with these options the server should be started in single process mode.

# Activating Debugging Options

The various options for debugging memory are now enabled in the `apr_general.h` header file in APR. The various options are enabled by uncommenting the define for the option you wish to use. The section of the code currently looks like this (contained in srclib/apr/include/apr_pools.h)

/*
#define ALLOC_DEBUG
#define POOL_DEBUG
#define ALLOC_USE_MALLOC
#define MAKE_TABLE_PROFILE
#define ALLOC_STATS
*/
typedef struct ap_pool_t {
union block_hdr *first;
union block_hdr *last;
struct cleanup *cleanups;
struct process_chain *subprocesses;
struct ap_pool_t *sub_pools;
struct ap_pool_t *sub_next;
struct ap_pool_t *sub_prev;
struct ap_pool_t *parent;
char *free_first_avail;
#ifdef ALLOC_USE_MALLOC
void *allocation_list;
#endif
#ifdef POOL_DEBUG
struct ap_pool_t *joined;
#endif
int (*apr_abort)(int retcode);
struct datastruct *prog_data;
} ap_pool_t;

To enable allocation debugging simply move the `#define ALLOC_DEBUG` above the start of the comments block and rebuild the server.

## Note

In order to use the various options the server must be rebuilt after editing the header file.