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.
29 #include "runmalloc.h"
43 #if defined(DEBUGMALLOC)
45 #define MALLOC_HASHTABLE_SIZE 16384
46 #define MallocHash(x) \
47 ((unsigned int)(((((long int)(x) >> 4) * 0xDEECE66D) >> 16) & (long int)0x3fff))
48 #define MAGIC_PREFIX 0xe4c483a1
49 #define MAGIC_POSTFIX 0x435bd0fa
55 int number_of_allocations;
61 #define LOCSIZE 1024 /* Maximum of 256 different locations */
62 static location_st location[LOCSIZE];
63 static unsigned int locations; /* Counter */
65 static unsigned int find_location(const char *filename, int line)
69 while (location[hash].filename && (location[hash].line != line ||
70 location[hash].filename != filename))
71 if (++hash == LOCSIZE)
73 if (!location[hash].filename)
77 location[hash].filename = filename;
78 location[hash].line = line;
82 #endif /* MEMLEAKSTATS */
85 /* The size of this struct should be a multiple of 4 bytes, just in case... */
87 unsigned int prefix_magicnumber;
91 unsigned int postfix_magicnumber;
94 #define SIZEOF_POSTFIX sizeof(postfix_blk_st)
95 #define SIZEOF_PREFIX sizeof(prefix_blk_st)
98 #else /* !MEMMAGICNUMS */
99 typedef void prefix_blk_st;
100 #define SIZEOF_PREFIX 0
101 #define SIZEOF_POSTFIX 0
102 #endif /* MEMMAGICNUMS */
104 typedef struct hash_entry_st {
105 struct hash_entry_st *next;
111 unsigned int location;
114 #endif /* MEMTIMESTATS */
115 #endif /* MEMLEAKSTATS */
118 #define memblkp(prefix_ptr) \
119 ((void *)((size_t)prefix_ptr + SIZEOF_PREFIX))
120 #define prefixp(memblk_ptr) \
121 ((prefix_blk_st *)((size_t)memblk_ptr - SIZEOF_PREFIX))
122 #define postfixp(memblk_ptr, size) \
123 ((postfix_blk_st *)((size_t)memblk_ptr + size))
125 static hash_entry_st *hashtable[MALLOC_HASHTABLE_SIZE];
127 static size_t mem_size = 0; /* Number of allocated bytes */
128 static unsigned int alloc_cnt = 0; /* Number of allocated blocks */
132 void report_memleak_stats(struct Client *sptr, int parc, char *parv[])
135 location_st *loc = location;
138 time_t till = CurrentTime;
139 time_t from = me.since;
142 location_st tmp_loc[LOCSIZE];
143 hash_entry_st **start;
144 memset(tmp_loc, 0, sizeof(tmp_loc));
146 till -= atoi(parv[3]);
148 from += atoi(parv[4]);
149 for (start = &hashtable[0];
150 start < &hashtable[MALLOC_HASHTABLE_SIZE]; ++start)
152 hash_entry_st *hash_entry;
153 for (hash_entry = *start; hash_entry; hash_entry = hash_entry->next)
154 if (hash_entry->when >= from && hash_entry->when <= till)
157 tmp_loc[hash_entry->location].size += hash_entry->size;
159 tmp_loc[hash_entry->location].number_of_allocations++;
163 if (MyUser(sptr) || Protocol(sptr->from) < 10)
164 sendto_one(sptr, ":%s NOTICE %s :Memory allocated between " TIME_T_FMT
165 " (server start + %s s) and " TIME_T_FMT " (CurrentTime - %s s):",
166 me.name, parv[0], from, parc > 4 ? parv[4] : "0", till,
167 parc > 3 ? parv[3] : "0");
169 sendto_one(sptr, "%s NOTICE %s%s :Memory allocated between " TIME_T_FMT
170 " (server start + %s s) and " TIME_T_FMT " (CurrentTime - %s s):",
171 NumServ(&me), NumNick(sptr), from, parc > 4 ? parv[4] : "0", till,
172 parc > 3 ? parv[3] : "0");
174 #endif /* MEMTIMESTATS */
175 for (hash = 0; hash < LOCSIZE; ++hash)
176 if (loc[hash].number_of_allocations > 0)
177 sendto_one(sptr, rpl_str(RPL_STATMEM), me.name, parv[0],
178 loc[hash].number_of_allocations,
179 location[hash].line, location[hash].filename
186 void *RunMalloc_memleak(size_t size, int line, const char *filename)
187 #else /* !MEMLEAKSTATS */
188 void *MyMalloc(size_t size)
189 #endif /* MEMLEAKSTATS */
192 hash_entry_st *hash_entry;
193 hash_entry_st **hashtablep;
200 if (!((ptr = (prefix_blk_st *)
201 malloc(SIZEOF_PREFIX + size + SIZEOF_POSTFIX)) &&
202 (hash_entry = (hash_entry_st *) malloc(sizeof(hash_entry_st)))))
210 hashtablep = &hashtable[MallocHash(ptr)];
211 hash_entry->next = *hashtablep;
212 *hashtablep = hash_entry;
213 hash_entry->ptr = ptr;
216 hash_entry->when = CurrentTime;
218 location[(hash_entry->location =
219 find_location(filename, line))].number_of_allocations++;
220 #endif /* MEMLEAKSTATS */
222 hash_entry->size = size;
224 location[hash_entry->location].size += size;
228 #endif /* MEMSIZESTATS */
230 ptr->prefix_magicnumber = MAGIC_PREFIX;
231 postfixp(memblkp(ptr), size)->postfix_magicnumber = MAGIC_POSTFIX;
234 Debug((DEBUG_MALLOC, "MyMalloc(%u) = %p", size, memblkp(ptr)));
240 void *RunCalloc_memleak(size_t nmemb, size_t size,
241 int line, const char *filename)
243 void *MyCalloc(size_t nmemb, size_t size)
244 #endif /* MEMLEAKSTATS */
249 if ((ptr = RunMalloc_memleak(size, line, filename)))
251 if ((ptr = MyMalloc(size)))
252 #endif /* MEMLEAKSTATS */
253 memset(ptr, 0, size);
257 int MyFree_test(void *memblk_ptr)
259 prefix_blk_st* prefix_ptr = prefixp(memblk_ptr);
260 hash_entry_st* hash_entry;
261 for (hash_entry = hashtable[MallocHash(prefix_ptr)];
262 hash_entry && hash_entry->ptr != prefix_ptr;
263 hash_entry = hash_entry->next);
264 return hash_entry ? 1 : 0;
267 void MyFree(void* memblk_ptr)
269 prefix_blk_st* prefix_ptr = prefixp(memblk_ptr);
270 hash_entry_st* hash_entry;
271 hash_entry_st* prev_hash_entry = NULL;
272 unsigned int hash = MallocHash(prefix_ptr);
274 Debug((DEBUG_MALLOC, "MyFree(%p)", memblk_ptr));
279 for (hash_entry = hashtable[hash];
280 hash_entry && hash_entry->ptr != prefix_ptr;
281 prev_hash_entry = hash_entry, hash_entry = hash_entry->next);
284 Debug((DEBUG_FATAL, "FREEING NON MALLOC PTR !!!"));
285 assert(0 != hash_entry);
288 if (prefix_ptr->prefix_magicnumber != MAGIC_PREFIX)
290 Debug((DEBUG_FATAL, "MAGIC_PREFIX CORRUPT !"));
291 assert(MAGIC_PREFIX == prefix_ptr->prefix_magicnumber);
293 prefix_ptr->prefix_magicnumber = 12345678;
294 if (postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber
297 Debug((DEBUG_FATAL, "MAGIC_POSTFIX CORRUPT !"));
298 assert(MAGIC_POSTFIX ==
299 postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber);
301 postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber = 87654321;
302 #endif /* MEMMAGICNUMS */
305 prev_hash_entry->next = hash_entry->next;
307 hashtable[hash] = hash_entry->next;
310 location[hash_entry->location].number_of_allocations--;
314 mem_size -= hash_entry->size;
317 location[hash_entry->location].size -= hash_entry->size;
320 /* Put 0xfefefefe.. in freed memory */
321 memset(prefix_ptr, 0xfe, hash_entry->size + SIZEOF_PREFIX);
322 #endif /* DEBUGMODE */
323 #endif /* MEMSIZESTATS */
330 void *RunRealloc_memleak(void *memblk_ptr, size_t size,
331 int line, const char *filename)
333 void *MyRealloc(void *memblk_ptr, size_t size)
334 #endif /* MEMLEAKSTATS */
337 prefix_blk_st *prefix_ptr = prefixp(memblk_ptr);
338 hash_entry_st *hash_entry, *prev_hash_entry = NULL;
339 hash_entry_st **hashtablep;
344 return RunMalloc_memleak(size, line, filename);
346 return MyMalloc(size);
347 #endif /* MEMLEAKSTATS */
354 for (hash_entry = hashtable[(hash = MallocHash(prefix_ptr))];
355 hash_entry && hash_entry->ptr != prefix_ptr;
356 prev_hash_entry = hash_entry, hash_entry = hash_entry->next);
359 Debug((DEBUG_FATAL, "REALLOCATING NON MALLOC PTR !!!"));
360 assert(0 != hash_entry);
364 if (prefix_ptr->prefix_magicnumber != MAGIC_PREFIX)
366 Debug((DEBUG_FATAL, "MAGIC_PREFIX CORRUPT !"));
367 assert(MAGIC_PREFIX == prefix_ptr->prefix_magicnumber);
369 if (postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber
372 Debug((DEBUG_FATAL, "MAGIC_POSTFIX CORRUPT !"));
373 assert(MAGIC_POSTFIX ==
374 postfixp(memblk_ptr, hash_entry->size)->postfix_magicnumber);
376 #endif /* MEMMAGICNUMS */
384 postfixp(memblkp(prefix_ptr), hash_entry->size)->postfix_magicnumber = 123456;
387 location[hash_entry->location].number_of_allocations--;
389 location[hash_entry->location].size -= hash_entry->size;
390 #endif /* MEMSIZESTATS */
391 #endif /* MEMLEAKSTATS */
394 (prefix_blk_st *) realloc(prefix_ptr,
395 SIZEOF_PREFIX + size + SIZEOF_POSTFIX)))
402 prev_hash_entry->next = hash_entry->next;
404 hashtable[hash] = hash_entry->next;
406 hashtablep = &hashtable[MallocHash(ptr)];
407 hash_entry->next = *hashtablep;
408 *hashtablep = hash_entry;
409 hash_entry->ptr = ptr;
412 hash_entry->when = CurrentTime;
414 location[(hash_entry->location =
415 find_location(filename, line))].number_of_allocations++;
416 #endif /* MEMLEAKSTATS */
418 mem_size += size - hash_entry->size;
419 hash_entry->size = size;
421 location[hash_entry->location].size += size;
423 #endif /* MEMSIZESTATS */
425 postfixp(memblkp(ptr), size)->postfix_magicnumber = MAGIC_POSTFIX;
428 Debug((DEBUG_MALLOC, ": MyRealloc(%p, %u) = %p",
429 memblk_ptr, size, memblkp(ptr)));
435 unsigned int get_alloc_cnt(void)
440 size_t get_mem_size(void)
444 #endif /* MEMSIZESTATS */
446 #endif /* !defined(DEBUGMALLOC) */