Re: 1.2b14: More malloc tracing tools

From: Henrik Nordstrom <hno@dont-contact.us>
Date: Sun, 08 Feb 1998 08:58:10 +0100

This is a multi-part message in MIME format.

--------------1FE7860977B92EF21B5F0E39
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Anthony Baxter wrote:
>
> wouldn't it be easier to just use Purify or a similar tool?

It is, if you have one available. But the built-in malloc tracing in
Squid was very simple to write, and then to extend ;-)

Here is yet another extension to the malloc tracing/debugging in squid.
A built-in memory-leak detector and memory map. This is only tested on
Linux, but I think it should work on many other OS:es as well (it
assumes that the data segment begins at _etext, and that pointers are
aligned on 4-byte boundaries). The leak detection code is enabled when
tracing is (--enable-xmalloc-debug-trace), as it uses the same data, and
the tracing alone is not that helpful.

Memory leaks are detected by searching for pointers in all referenced
memory, beginning with the data segment and then follow all pointers
from there. Allocations where we have no pointer pointing at them is
reported as leaked. (I got the idea from a garbage collector ;-)

When squid exits, it shows report on leaked memory and a full memory map
of memory that is allocated and referenced..

This patch requires my previous patch, as it likes to print source lines
references to where the memory was allocated.

/Henrik

--------------1FE7860977B92EF21B5F0E39
Content-Type: text/plain; charset=us-ascii; name="squid-1.2.beta14.leak_detector_and_memory_map.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="squid-1.2.beta14.leak_detector_and_memory_map.patch"

Index: squid/src/main.c
diff -u squid/src/main.c:1.1.1.11.2.1 squid/src/main.c:1.1.1.11.2.2
--- squid/src/main.c:1.1.1.11.2.1 Sun Feb 8 02:40:54 1998
+++ squid/src/main.c Sun Feb 8 08:23:56 1998
@@ -727,22 +727,34 @@
     dumpMallocStats();
     storeLogClose();
     accessLogClose();
-#if PURIFY
+#if PURIFY || XMALLOC_TRACE
     configFreeMemory();
     storeFreeMemory();
     dnsFreeMemory();
     redirectFreeMemory();
- stmemFreeMemory();
+ /*stmemFreeMemory(); */
     netdbFreeMemory();
     ipcacheFreeMemory();
     fqdncacheFreeMemory();
     asnFreeMemory();
 #endif
+#if WHY_DO_THIS
     file_close(0);
     file_close(1);
     file_close(2);
+#endif
     fdDumpOpen();
     fdFreeMemory();
+#if XMALLOC_TRACE
+ {
+ extern int xmalloc_total;
+ extern void xmalloc_find_leaks(void);
+ extern void xmalloc_dump_map(void);
+ xmalloc_find_leaks();
+ xmalloc_dump_map();
+ debug(1, 0) ("Memory used after shutdown: %d\n",xmalloc_total);
+ }
+#endif
     debug(1, 0) ("Squid Cache (Version %s): Exiting normally.\n",
         version_string);
     fclose(debug_log);
Index: squid/src/store_dir.c
diff -u squid/src/store_dir.c:1.1.1.9 squid/src/store_dir.c:1.1.1.9.2.1
--- squid/src/store_dir.c:1.1.1.9 Sun Feb 8 02:24:59 1998
+++ squid/src/store_dir.c Sun Feb 8 08:04:28 1998
@@ -270,7 +270,7 @@
 void
 storeDirSwapLog(const StoreEntry * e, int op)
 {
- storeSwapData *s = xcalloc(1, sizeof(storeSwapData));
+ storeSwapData *s;
     int dirn;
     dirn = e->swap_file_number >> SWAP_DIR_SHIFT;
     assert(dirn < Config.cacheSwap.n_configured);
@@ -287,6 +287,7 @@
      */
     if (EBIT_TEST(e->flag, ENTRY_SPECIAL))
         return;
+ s = xcalloc(1, sizeof(storeSwapData));
     s->op = (char) op;
     s->swap_file_number = e->swap_file_number;
     s->timestamp = e->timestamp;
Index: squid/lib/util.c
===================================================================
RCS file: /usr/src/CVS/squid/lib/util.c,v
retrieving revision 1.1.1.7.2.1
retrieving revision 1.1.1.7.2.3
diff -u -r1.1.1.7.2.1 -r1.1.1.7.2.3
--- util.c 1998/02/08 01:40:54 1.1.1.7.2.1
+++ util.c 1998/02/08 07:38:46 1.1.1.7.2.3
@@ -1,6 +1,6 @@
 
 /*
- * $Id: util.c,v 1.1.1.7.2.1 1998/02/08 01:40:54 henrik Exp $
+ * $Id: util.c,v 1.1.1.7.2.3 1998/02/08 07:38:46 henrik Exp $
  *
  * DEBUG:
  * AUTHOR: Harvest Derived
@@ -180,6 +180,7 @@
 char *xmalloc_func="";
 static int xmalloc_count=0;
 int xmalloc_trace=0; /* Enable with -m option */
+size_t xmalloc_total = 0;
 #undef xmalloc
 #undef xfree
 #undef xxfree
@@ -191,22 +192,21 @@
 #if XMALLOC_DEBUG
 #define DBG_ARRY_SZ (1<<10)
 #define DBG_ARRY_BKTS (1<<8)
-static void *malloc_ptrs[DBG_ARRY_BKTS][DBG_ARRY_SZ];
+static void *(*malloc_ptrs)[DBG_ARRY_SZ];
 static int malloc_size[DBG_ARRY_BKTS][DBG_ARRY_SZ];
 #if XMALLOC_TRACE
-static void *malloc_file[DBG_ARRY_BKTS][DBG_ARRY_SZ];
-static int malloc_line[DBG_ARRY_BKTS][DBG_ARRY_SZ];
+static char *malloc_file[DBG_ARRY_BKTS][DBG_ARRY_SZ];
+static short malloc_line[DBG_ARRY_BKTS][DBG_ARRY_SZ];
 static int malloc_count[DBG_ARRY_BKTS][DBG_ARRY_SZ];
 #endif
 static int dbg_initd = 0;
-static int B = 0;
-static int I = 0;
-static void *P;
-static void *Q;
 
 static void
 check_init(void)
 {
+ int B=0,I=0;
+ /* calloc the ptrs so that we don't see them when hunting lost memory */
+ malloc_ptrs=calloc(DBG_ARRY_BKTS,sizeof(*malloc_ptrs));
     for (B = 0; B < DBG_ARRY_BKTS; B++) {
         for (I = 0; I < DBG_ARRY_SZ; I++) {
             malloc_ptrs[B][I] = NULL;
@@ -224,6 +224,7 @@
 static void
 check_free(void *s)
 {
+ int B,I;
     B = (((int) s) >> 4) & 0xFF;
     for (I = 0; I < DBG_ARRY_SZ; I++) {
         if (malloc_ptrs[B][I] != s)
@@ -246,11 +247,13 @@
 static void
 check_malloc(void *p, size_t sz)
 {
+ void *P,*Q;
+ int B,I;
     if (!dbg_initd)
         check_init();
     B = (((int) p) >> 4) & 0xFF;
     for (I = 0; I < DBG_ARRY_SZ; I++) {
- if ((P = malloc_ptrs[B][I]) == NULL)
+ if (!(P = malloc_ptrs[B][I]))
             continue;
         Q = P + malloc_size[B][I];
         if (P <= p && p < Q) {
@@ -260,7 +263,7 @@
         }
     }
     for (I = 0; I < DBG_ARRY_SZ; I++) {
- if ((P = malloc_ptrs[B][I]))
+ if (malloc_ptrs[B][I])
             continue;
         malloc_ptrs[B][I] = p;
         malloc_size[B][I] = (int) sz;
@@ -280,6 +283,7 @@
 int
 mallocblksize(void *p)
 {
+ int B,I;
     B = (((int) p) >> 4) & 0xFF;
     for (I = 0; I < DBG_ARRY_SZ; I++) {
         if (malloc_ptrs[B][I] == p)
@@ -293,6 +297,7 @@
 static char *
 malloc_file_name(void *p)
 {
+ int B,I;
     B = (((int) p) >> 4) & 0xFF;
     for (I = 0; I < DBG_ARRY_SZ; I++) {
         if (malloc_ptrs[B][I] == p)
@@ -303,6 +308,7 @@
 int
 malloc_line_number(void *p)
 {
+ int B,I;
     B = (((int) p) >> 4) & 0xFF;
     for (I = 0; I < DBG_ARRY_SZ; I++) {
         if (malloc_ptrs[B][I] == p)
@@ -313,6 +319,7 @@
 int
 malloc_number(void *p)
 {
+ int B,I;
     B = (((int) p) >> 4) & 0xFF;
     for (I = 0; I < DBG_ARRY_SZ; I++) {
         if (malloc_ptrs[B][I] == p)
@@ -329,14 +336,13 @@
     size_t accounted = statMemoryAccounted();
     size_t mi = mp.uordblks + mp.usmblks + mp.hblkhd;
     size_t sz;
- static size_t total = 0;
     sz = mallocblksize(p) * sign;
- total += sz;
+ xmalloc_total += sz;
     xmalloc_count += sign>0;
     if (xmalloc_trace) {
         fprintf(stderr, "%c%8p size=%5d/%d acc=%5d/%d mallinfo=%5d/%d %s:%d %s",
             sign>0 ? '+':'-',p,
- (int) total - last_total, (int) total,
+ (int) xmalloc_total - last_total, (int) xmalloc_total,
             (int) accounted - last_accounted, (int) accounted,
             (int) mi - last_mallinfo, (int) mi,
             xmalloc_file, xmalloc_line, xmalloc_func);
@@ -345,11 +351,92 @@
         else
             fprintf(stderr," %d\n",xmalloc_count);
     }
- last_total = total;
+ last_total = xmalloc_total;
     last_accounted = accounted;
     last_mallinfo = mi;
 }
-
+short (*malloc_refs)[DBG_ARRY_SZ];
+char **xmalloc_leak_test;
+#define XMALLOC_LEAK_CHECKED (1<<15)
+#define XMALLOC_LEAK_ALIGN (4)
+static int xmalloc_scan_region(void *start, int size)
+{
+ int B,I;
+ char *ptr=start;
+ char *end=ptr+size-XMALLOC_LEAK_ALIGN;
+ int found=0;
+ while(ptr <= end) {
+ void *p=*(void **)ptr;
+ if (p && p!=start) {
+ B = (((int) p) >> 4) & 0xFF;
+ for (I = 0; I < DBG_ARRY_SZ; I++) {
+ if (malloc_ptrs[B][I] == p) {
+ if (!malloc_refs[B][I])
+ found++;
+ malloc_refs[B][I]++;
+ }
+ }
+ }
+ ptr+=XMALLOC_LEAK_ALIGN;
+ }
+ return found;
+}
+extern void _etext;
+void xmalloc_find_leaks(void)
+{
+ int B,I;
+ int found;
+ int leak_sum=0;
+ fprintf(stderr,"Searching for memory references...\n");
+ malloc_refs=xcalloc(DBG_ARRY_BKTS,sizeof(*malloc_refs));
+ found=xmalloc_scan_region(&_etext,(void *)sbrk(0)-(void *)&_etext);
+ while(found) {
+ found=0;
+ for(I=0;I<DBG_ARRY_SZ && !found;I++) {
+ for(B=0;B<DBG_ARRY_BKTS;B++) {
+ if (malloc_refs[B][I] > 0) {
+ malloc_refs[B][I] |= XMALLOC_LEAK_CHECKED;
+ found+=xmalloc_scan_region(malloc_ptrs[B][I],
+ malloc_size[B][I]);
+ }
+ }
+ }
+ }
+ for(B=0;B<DBG_ARRY_BKTS;B++) {
+ for(I=0;I<DBG_ARRY_SZ;I++) {
+ if (malloc_ptrs[B][I] && malloc_refs[B][I] == 0) {
+ /* Found a leak... */
+ fprintf(stderr, "Leak found: %p",malloc_ptrs[B][I]);
+ fprintf(stderr, " %s",malloc_file[B][I]);
+ fprintf(stderr, ":%d",malloc_line[B][I]);
+ fprintf(stderr, " size %d\n",malloc_size[B][I]);
+ fprintf(stderr, " allocation %d",malloc_count[B][I]);
+ leak_sum += malloc_size[B][I];
+ }
+ }
+ }
+ if (leak_sum) {
+ fprintf(stderr, "Total leaked memory: %d\n",leak_sum);
+ } else {
+ fprintf(stderr, "No memory leaks detected\n");
+ }
+}
+void xmalloc_dump_map(void)
+{
+ int B,I;
+ fprintf(stderr, "----- Memory map ----\n");
+ for(B=0;B<DBG_ARRY_BKTS;B++) {
+ for(I=0;I<DBG_ARRY_SZ;I++) {
+ if (malloc_ptrs[B][I]) {
+ printf("%p %s:%d size %d allocation %d references %d\n",
+ malloc_ptrs[B][I], malloc_file[B][I], malloc_line[B][I],
+ malloc_size[B][I], malloc_count[B][I],
+ malloc_refs[B][I]&(XMALLOC_LEAK_CHECKED-1));
+ }
+ }
+ }
+ fprintf(stderr,"----------------------\n");
+}
 #endif /* XMALLOC_TRACE */
 
 /*

--------------1FE7860977B92EF21B5F0E39--
Received on Tue Jul 29 2003 - 13:15:46 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:11:42 MST