2 * Run's malloc/realloc/calloc/free DEBUG tools v2.0
4 * (c) Copyright 1996, 1997
8 * 1024/624ACAD5 1997/01/26 Carlo Wood, Run on IRC <carlo@runaway.xs4all.nl>
9 * Key fingerprint = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61
10 * Get key from pgp-public-keys server or
11 * finger carlo@runaway.xs4all.nl for public key (dialin, try at 21-22h GMT).
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 #define MALLOC_HASHTABLE_SIZE 16384
37 #define MallocHash(x) \
38 ((unsigned int)(((((long int)(x) >> 4) * 0xDEECE66D) >> 16) & (long int)0x3fff))
39 #define MAGIC_PREFIX 0xe4c483a1
40 #define MAGIC_POSTFIX 0x435bd0fa
46 int number_of_allocations;
52 #define LOCSIZE 1024 /* Maximum of 256 different locations */
53 static location_st location[LOCSIZE];
54 static unsigned int locations; /* Counter */
56 static unsigned int find_location(const char *filename, int line)
58 register unsigned int hash;
60 while (location[hash].filename && (location[hash].line != line ||
61 location[hash].filename != filename))
62 if (++hash == LOCSIZE)
64 if (!location[hash].filename)
68 location[hash].filename = filename;
69 location[hash].line = line;
76 /* The size of this struct should be a multiple of 4 bytes, just in case... */
79 unsigned int prefix_magicnumber;
83 #define SIZEOF_PREFIX sizeof(prefix_blk_st)
85 typedef void prefix_blk_st;
86 #define SIZEOF_PREFIX 0
91 unsigned int postfix_magicnumber;
94 #define SIZEOF_POSTFIX sizeof(postfix_blk_st)
97 #define SIZEOF_POSTFIX 0
100 typedef struct hash_entry_st {
101 struct hash_entry_st *next;
107 unsigned int location;
114 #define memblkp(prefix_ptr) \
115 ((void *)((size_t)prefix_ptr + SIZEOF_PREFIX))
116 #define prefixp(memblk_ptr) \
117 ((prefix_blk_st *)((size_t)memblk_ptr - SIZEOF_PREFIX))
118 #define postfixp(memblk_ptr, size) \
119 ((postfix_blk_st *)((size_t)memblk_ptr + size))
121 static hash_entry_st *hashtable[MALLOC_HASHTABLE_SIZE];
123 static size_t mem_size = 0; /* Number of allocated bytes */
124 static unsigned int alloc_cnt = 0; /* Number of allocated blocks */
134 #include "numnicks.h"
136 void report_memleak_stats(aClient *sptr, int parc, char *parv[])
139 location_st *loc = location;
143 time_t from = me.since;
146 location_st tmp_loc[LOCSIZE];
147 hash_entry_st **start;
148 memset(tmp_loc, 0, sizeof(tmp_loc));
150 till -= atoi(parv[3]);
152 from += atoi(parv[4]);
153 for (start = &hashtable[0];
154 start < &hashtable[MALLOC_HASHTABLE_SIZE]; ++start)
156 hash_entry_st *hash_entry;
157 for (hash_entry = *start; hash_entry; hash_entry = hash_entry->next)
158 if (hash_entry->when >= from && hash_entry->when <= till)
161 tmp_loc[hash_entry->location].size += hash_entry->size;
163 tmp_loc[hash_entry->location].number_of_allocations++;
167 if (MyUser(sptr) || Protocol(sptr->from) < 10)
168 sendto_one(sptr, ":%s NOTICE %s :Memory allocated between " TIME_T_FMT
169 " (server start + %s s) and " TIME_T_FMT " (now - %s s):",
170 me.name, parv[0], from, parc > 4 ? parv[4] : "0", till,
171 parc > 3 ? parv[3] : "0");
173 sendto_one(sptr, "%s NOTICE %s%s :Memory allocated between " TIME_T_FMT
174 " (server start + %s s) and " TIME_T_FMT " (now - %s s):",
175 NumServ(&me), NumNick(sptr), from, parc > 4 ? parv[4] : "0", till,
176 parc > 3 ? parv[3] : "0");
179 for (hash = 0; hash < LOCSIZE; ++hash)
180 if (loc[hash].number_of_allocations > 0)
181 sendto_one(sptr, rpl_str(RPL_STATMEM), me.name, parv[0],
182 loc[hash].number_of_allocations,
183 location[hash].line, location[hash].filename
190 void *RunMalloc_memleak(size_t size, int line, const char *filename)
192 void *RunMalloc(size_t size)
195 register prefix_blk_st *ptr;
196 register hash_entry_st *hash_entry;
197 register hash_entry_st **hashtablep;
204 if (!((ptr = (prefix_blk_st *)
205 malloc(SIZEOF_PREFIX + size + SIZEOF_POSTFIX)) &&
206 (hash_entry = (hash_entry_st *) malloc(sizeof(hash_entry_st)))))
210 Debug((DEBUG_FATAL, "Out of memory !"));
214 hashtablep = &hashtable[MallocHash(ptr)];
215 hash_entry->next = *hashtablep;
216 *hashtablep = hash_entry;
217 hash_entry->ptr = ptr;
220 hash_entry->when = now;
222 location[(hash_entry->location =
223 find_location(filename, line))].number_of_allocations++;
226 hash_entry->size = size;
228 location[hash_entry->location].size += size;
234 ptr->prefix_magicnumber = MAGIC_PREFIX;
235 postfixp(memblkp(ptr), size)->postfix_magicnumber = MAGIC_POSTFIX;
238 Debug((DEBUG_DEBUG, "RunMalloc(%u) = %p", size, memblkp(ptr)));
244 void *RunCalloc_memleak(size_t nmemb, size_t size,
245 int line, const char *filename)
247 void *RunCalloc(size_t nmemb, size_t size)
253 if ((ptr = RunMalloc_memleak(size, line, filename)))
255 if ((ptr = RunMalloc(size)))
257 memset(ptr, 0, size);
261 int RunFree_test(void *memblk_ptr)
263 register prefix_blk_st *prefix_ptr = prefixp(memblk_ptr);
264 register hash_entry_st *hash_entry;
265 for (hash_entry = hashtable[MallocHash(prefix_ptr)];
266 hash_entry && hash_entry->ptr != prefix_ptr;
267 hash_entry = hash_entry->next);
268 return hash_entry ? 1 : 0;
271 void RunFree(void *memblk_ptr)
273 register prefix_blk_st *prefix_ptr = prefixp(memblk_ptr);
274 register hash_entry_st *hash_entry, *prev_hash_entry = NULL;
275 unsigned int hash = MallocHash(prefix_ptr);
277 Debug((DEBUG_DEBUG, "RunFree(%p)", memblk_ptr));
282 for (hash_entry = hashtable[hash];
283 hash_entry && hash_entry->ptr != prefix_ptr;
284 prev_hash_entry = hash_entry, hash_entry = hash_entry->next);
287 Debug((DEBUG_FATAL, "FREEING NON MALLOC PTR !!!"));
291 if (prefix_ptr->prefix_magicnumber != MAGIC_PREFIX)
293 Debug((DEBUG_FATAL, "MAGIC_PREFIX CORRUPT !"));
296 prefix_ptr->prefix_magicnumber = 12345678;
297 if (postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber
300 Debug((DEBUG_FATAL, "MAGIC_POSTFIX CORRUPT !"));
303 postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber = 87654321;
307 prev_hash_entry->next = hash_entry->next;
309 hashtable[hash] = hash_entry->next;
312 location[hash_entry->location].number_of_allocations--;
316 mem_size -= hash_entry->size;
319 location[hash_entry->location].size -= hash_entry->size;
322 /* Put 0xfefefefe.. in freed memory */
324 memset(prefix_ptr, 0xfe, hash_entry->size + SIZEOF_PREFIX);
327 register char *p = prefix_ptr;
328 size_t len = hash_entry->size + SIZEOF_PREFIX;
341 void *RunRealloc_memleak(void *memblk_ptr, size_t size,
342 int line, const char *filename)
344 void *RunRealloc(void *memblk_ptr, size_t size)
347 register prefix_blk_st *ptr;
348 register prefix_blk_st *prefix_ptr = prefixp(memblk_ptr);
349 register hash_entry_st *hash_entry, *prev_hash_entry = NULL;
350 register hash_entry_st **hashtablep;
355 return RunMalloc_memleak(size, line, filename);
357 return RunMalloc(size);
365 for (hash_entry = hashtable[(hash = MallocHash(prefix_ptr))];
366 hash_entry && hash_entry->ptr != prefix_ptr;
367 prev_hash_entry = hash_entry, hash_entry = hash_entry->next);
370 Debug((DEBUG_FATAL, "REALLOCATING NON MALLOC PTR !!!"));
375 if (prefix_ptr->prefix_magicnumber != MAGIC_PREFIX)
377 Debug((DEBUG_FATAL, "MAGIC_PREFIX CORRUPT !"));
380 if (postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber
383 Debug((DEBUG_FATAL, "MAGIC_POSTFIX CORRUPT !"));
394 postfixp(memblkp(prefix_ptr), hash_entry->size)->postfix_magicnumber = 123456;
397 location[hash_entry->location].number_of_allocations--;
399 location[hash_entry->location].size -= hash_entry->size;
404 (prefix_blk_st *) realloc(prefix_ptr,
405 SIZEOF_PREFIX + size + SIZEOF_POSTFIX)))
407 Debug((DEBUG_FATAL, "RunRealloc: Out of memory :"));
412 prev_hash_entry->next = hash_entry->next;
414 hashtable[hash] = hash_entry->next;
416 hashtablep = &hashtable[MallocHash(ptr)];
417 hash_entry->next = *hashtablep;
418 *hashtablep = hash_entry;
419 hash_entry->ptr = ptr;
422 hash_entry->when = now;
424 location[(hash_entry->location =
425 find_location(filename, line))].number_of_allocations++;
428 mem_size += size - hash_entry->size;
429 hash_entry->size = size;
431 location[hash_entry->location].size += size;
435 postfixp(memblkp(ptr), size)->postfix_magicnumber = MAGIC_POSTFIX;
438 Debug((DEBUG_DEBUG, ": RunRealloc(%p, %u) = %p",
439 memblk_ptr, size, memblkp(ptr)));
445 unsigned int get_alloc_cnt(void)
450 size_t get_mem_size(void)
456 #endif /* DEBUGMALLOC */