debugging.html revision 7d9f2bf92f3b96b3d651365013e5da845849571b
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org" />
<title>Debugging Memory Allocation in APR</title>
</head>
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
vlink="#000080" alink="#FF0000">
<!--#include virtual="header.html" -->
<h1 align="CENTER">Debugging Memory Allocation in APR<br />
</h1>
<p>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.</p>
<ul>
<li><a href="#options">Available debugging options</a></li>
<li><a href="#combo">Allowable combinations</a></li>
<li><a href="#howto">How to activate debugging</a></li>
</ul>
<hr />
<h2>Allocation Debugging</h2>
<h3>ALLOC_DEBUG</h3>
<p><em>Debugging support: Define this to enable code which
helps detect re-use of freed memory and other such
nonsense.</em></p>
<p>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 0xa5s then you know something used data that's been freed or
uninitialized.</p>
<h2>Malloc Support</h2>
<h3>ALLOC_USE_MALLOC</h3>
<p><em>If defined all allocations will be done with malloc and
free()d appropriately at the end.</em></p>
<p>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.</p>
<h2>Pool Debugging</h2>
<h3>POOL_DEBUG</h3>
<p><em>This is intended to detect cases where the wrong pool is
used when assigning data to an object in another pool.</em></p>
<p>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.</p>
<h2>Table Debugging</h2>
<h3>MAKE_TABLE_PROFILE</h3>
<p><em>Provide diagnostic information about make_table() calls
which are possibly too small.</em></p>
<p>This requires a recent gcc which supports
__builtin_return_address(). The error_log output will be a
message such as:</p>
<pre>
table_push: apr_table_t created by 0x804d874 hit limit of 10
</pre>
<p>Use "<em><strong>l *0x804d874</strong></em>" 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.</p>
<h2>Allocation Statistics</h2>
<h3>ALLOC_STATS</h3>
<p><em>Provide some statistics on the cost of
allocations.</em></p>
<p>This requires a bit of an understanding of how alloc.c
works.</p>
<hr />
<h2>Allowable Combinations</h2>
<p>Not all the options outlined above can be activated at the
same time. the following table gives more information.</p>
<table width="80%">
<tr>
<th width="25%">Option 1</th>
<th width="15%">ALLOC<br />
DEBUG</th>
<th width="15%">ALLOC<br />
USE<br />
MALLOC</th>
<th width="15%">POOL<br />
DEBUG</th>
<th width="15%">MAKE<br />
TABLE<br />
PROFILE</th>
<th width="15%">ALLOC<br />
STATS</th>
</tr>
<tr>
<td>ALLOC_DEBUG</td>
<td bgcolor="#ff0000">&nbsp;</td>
<td align="center">No</td>
<td align="center">Yes</td>
<td align="center">Yes</td>
<td align="center">Yes</td>
</tr>
<tr>
<td>ALLOC_USE<br />
MALLOC</td>
<td align="center">No</td>
<td bgcolor="#ff0000">&nbsp;</td>
<td align="center">No</td>
<td align="center">No</td>
<td align="center">No</td>
</tr>
<tr>
<td>POOL_DEBUG</td>
<td align="center">Yes</td>
<td align="center">No</td>
<td bgcolor="#ff0000">&nbsp;</td>
<td align="center">Yes</td>
<td align="center">Yes</td>
</tr>
<tr>
<td>MAKE_TABLE<br />
PROFILE</td>
<td align="center">Yes</td>
<td align="center">No</td>
<td align="center">Yes</td>
<td bgcolor="#ff0000">&nbsp;</td>
<td align="center">Yes</td>
</tr>
<tr>
<td>ALLOC_STATS</td>
<td align="center">Yes</td>
<td align="center">No</td>
<td align="center">Yes</td>
<td align="center">Yes</td>
<td bgcolor="#ff0000">&nbsp;</td>
</tr>
</table>
<p>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.</p>
<hr />
<h2>Activating Debugging Options</h2>
<p>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
<em>(contained in srclib/apr/include/apr_pools.h)</em></p>
<pre>
/*
#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;
</pre>
<p>To enable allocation debugging simply move the #define
ALLOC_DEBUG above the start of the comments block and rebuild
the server.</p>
<strong>NB. In order to use the various options the server MUST
be rebuilt after editing the header file.</strong>
<!--#include virtual="footer.html" -->
</body>
</html>