4 xmalloc.c - Simple malloc debugging library implementation
6 This software is released under a BSD-style license.
7 See the file LICENSE for details and copyright.
14 - group dumps by source location
20 #define XMALLOC_INTERNAL 1
28 typedef struct hashTableItemRec {
34 struct hashTableItemRec *next;
38 hashTableItem **table;
41 static int xmalloc_peak;
43 static int xmalloc_peak_blocks;
44 int xmalloc_current_blocks;
45 static int xmalloc_fail_after;
48 #define TABLE_MASK ((1 << TABLE_BITS) - 1)
49 #define TABLE_SIZE (1 << TABLE_BITS)
56 tbl = malloc(sizeof(*tbl));
60 tbl->table = calloc(TABLE_SIZE, sizeof(*tbl->table));
62 if (tbl->table == NULL)
73 hash_void_ptr(void *ptr)
78 /* I took this hash function just off the top of my head, I have
79 no idea whether it is bad or very bad. */
81 for (i = 0; i < (int)sizeof(ptr)*8 / TABLE_BITS; i++)
83 hash ^= (unsigned long)ptr >> i*8;
91 hash_table_add(hashTable *tbl, void *ptr, int bytes,
92 const char *file, int line, const char *func)
95 hashTableItem *item, *new;
97 i = hash_void_ptr(ptr);
101 while (item->next != NULL)
104 new = malloc(sizeof(*new));
117 xmalloc_current += bytes;
118 if (xmalloc_current > xmalloc_peak)
119 xmalloc_peak = xmalloc_current;
120 xmalloc_current_blocks++;
121 if (xmalloc_current_blocks > xmalloc_peak_blocks)
122 xmalloc_peak_blocks = xmalloc_current_blocks;
126 hash_table_del(hashTable *tbl, void *ptr)
129 hashTableItem *item, *prev;
131 i = hash_void_ptr(ptr);
133 item = tbl->table[i];
136 printf("xfree: invalid ptr %p\n", ptr);
140 while (item->ptr != ptr)
145 if (item->ptr != ptr)
147 printf("xfree: invalid ptr %p\n", ptr);
151 xmalloc_current -= item->bytes;
152 xmalloc_current_blocks--;
156 prev->next = item->next;
161 tbl->table[i] = item->next;
166 static hashTable *xmalloc_table = NULL;
171 if (xmalloc_table == NULL)
173 xmalloc_table = hash_table_new();
175 xmalloc_peak_blocks = 0;
177 xmalloc_current_blocks = 0;
178 xmalloc_fail_after = -1;
180 assert(xmalloc_table != NULL);
181 assert(xmalloc_table->table != NULL);
191 xmalloc_configure(int fail_after)
194 xmalloc_fail_after = fail_after;
198 xmalloc_dump_leaks(void)
202 int leaked_bytes = 0;
207 for (i = 0; i < TABLE_SIZE; i++)
209 item = xmalloc_table->table[i];
212 printf("%s:%d: %s: %d bytes at %p not freed\n",
213 item->file, item->line, item->func, item->bytes, item->ptr);
215 leaked_bytes += item->bytes;
220 printf("No memory leaks.\n");
222 printf("%d unfreed memory chuncks, total %d unfreed bytes.\n",
223 num_leaks, leaked_bytes);
224 printf("Peak memory consumption %d bytes (%.1f kB, %.1f MB) in %d blocks ",
225 xmalloc_peak, (double)xmalloc_peak / 1024,
226 (double)xmalloc_peak / (1024*1024), xmalloc_peak_blocks);
228 if (xmalloc_peak_blocks)
229 printf("%d", ((xmalloc_peak + xmalloc_peak_blocks / 2)
230 / xmalloc_peak_blocks));
233 printf(" bytes per block).\n");
239 xmalloc_impl(size_t size, const char *file, int line, const char *func)
246 if (xmalloc_fail_after == 0)
248 xmalloc_fail_after = -2;
250 printf("xmalloc: forced failure %s:%d: %s\n", file, line, func);
254 else if (xmalloc_fail_after == -2)
256 printf("xmalloc: called after failure from %s:%d: %s\n",
260 else if (xmalloc_fail_after > 0)
261 xmalloc_fail_after--;
265 hash_table_add(xmalloc_table, ptr, (int)size, file, line, func);
270 xcalloc_impl(size_t nmemb, size_t size, const char *file, int line,
278 if (xmalloc_fail_after == 0)
280 xmalloc_fail_after = -2;
282 printf("xcalloc: forced failure %s:%d: %s\n", file, line, func);
286 else if (xmalloc_fail_after == -2)
288 printf("xcalloc: called after failure from %s:%d: %s\n",
292 else if (xmalloc_fail_after > 0)
293 xmalloc_fail_after--;
295 ptr = calloc(nmemb, size);
297 hash_table_add(xmalloc_table, ptr, (int)(nmemb * size), file, line, func);
302 xfree_impl(void *ptr, const char *file, int line, const char *func)
304 /*LINTED*/(void)&file;
305 /*LINTED*/(void)&line;
306 /*LINTED*/(void)&func;
310 hash_table_del(xmalloc_table, ptr);
315 xrealloc_impl(void *ptr, size_t new_size, const char *file, int line,
322 assert(new_size > 0);
324 if (xmalloc_fail_after == 0)
326 xmalloc_fail_after = -2;
329 else if (xmalloc_fail_after == -2)
331 printf("xrealloc: called after failure from %s:%d: %s\n",
335 else if (xmalloc_fail_after > 0)
336 xmalloc_fail_after--;
338 new_ptr = realloc(ptr, new_size);
341 hash_table_del(xmalloc_table, ptr);
342 hash_table_add(xmalloc_table, new_ptr, (int)new_size, file, line, func);