diff --git a/src/array.c b/src/array.c index bee20d05f7b249f4a8d5cbda9c1e226fa5a29d0d..77d706a009a371fbc28fe600c08e393838676403 100644 --- a/src/array.c +++ b/src/array.c @@ -23,7 +23,7 @@ #include "stuff.h" #include "bignum.h" -RCSID("$Id: array.c,v 1.61 2000/02/17 18:57:36 hubbe Exp $"); +RCSID("$Id: array.c,v 1.62 2000/03/07 21:23:41 hubbe Exp $"); struct array empty_array= { @@ -1958,6 +1958,13 @@ void zap_all_arrays(void) if(!(next=a->next)) fatal("Null pointer in array list.\n"); + while((next=a->next) != &empty_array && a->refs == 1) + { + add_ref(next); + free_program(a); + a=next; + } + free_array(a); a=next; } while (a != & empty_array); diff --git a/src/dmalloc.h b/src/dmalloc.h index de42a6518d2547e3176ce5b6e1fe5eb5b9f08df6..ccf44a3688ecbb2f66dcc98ec268b3444d55d975 100644 --- a/src/dmalloc.h +++ b/src/dmalloc.h @@ -1,5 +1,5 @@ /* - * $Id: dmalloc.h,v 1.18 1999/10/30 06:31:02 mast Exp $ + * $Id: dmalloc.h,v 1.19 2000/03/07 21:23:41 hubbe Exp $ */ extern char *debug_xalloc(long); @@ -28,6 +28,7 @@ extern int debug_malloc_register_fd(int, const char *, int); extern int debug_malloc_close_fd(int, const char *, int); void *debug_malloc_update_location(void *,const char *, int); +void search_all_memheaders_for_references(void); /* Beware! names of named memory regions are never ever freed!! /Hubbe */ void *debug_malloc_name(void *p,const char *fn, int line); @@ -82,4 +83,5 @@ void dmalloc_accept_leak(void *); #define debug_free(X,Y,Z,Q) free((X)) #define debug_malloc_name(P,FN,LINE) #define debug_malloc_copy_names(p,p2) +#define search_all_memheaders_for_references() #endif diff --git a/src/gc.c b/src/gc.c index 69dfa1effc3c117ab0a68ca8bfeb47ca7e64020f..97dc66cee4a14a501fe5c208b8be4a2c3467fa29 100644 --- a/src/gc.c +++ b/src/gc.c @@ -29,7 +29,7 @@ struct callback *gc_evaluator_callback=0; #include "block_alloc.h" -RCSID("$Id: gc.c,v 1.48 2000/02/22 21:28:52 hubbe Exp $"); +RCSID("$Id: gc.c,v 1.49 2000/03/07 21:23:41 hubbe Exp $"); /* Run garbage collect approximate every time we have * 20 percent of all arrays, objects and programs is @@ -236,25 +236,9 @@ int debug_gc_check(void *x, TYPE_T t, void *data) return ret; } -void describe_something(void *a, int t, int dm) +void low_describe_something(void *a, int t, int dm) { struct program *p=(struct program *)a; - if(!a) return; - -#ifdef DEBUG_MALLOC - if(dm) - debug_malloc_dump_references(a); -#endif - - if(t==-1) - { - fprintf(stderr,"**Location description: %s\n",(char *)a); - return; - } - - fprintf(stderr,"**Location: %p Type: %s Refs: %d\n",a, - get_name_of_type(t), - *(INT32 *)a); switch(t) { @@ -358,6 +342,31 @@ void describe_something(void *a, int t, int dm) break; } } +} + +void describe_something(void *a, int t, int dm) +{ + struct program *p=(struct program *)a; + if(!a) return; + + if(t==-1) + { + fprintf(stderr,"**Location description: %s\n",(char *)a); + return; + } + + fprintf(stderr,"**Location: %p Type: %s Refs: %d\n",a, + get_name_of_type(t), + *(INT32 *)a); + + low_describe_something(a,t,dm); + +#ifdef DEBUG_MALLOC + if(dm) + debug_malloc_dump_references(a); +#endif + + fprintf(stderr,"*******************\n"); } diff --git a/src/main.c b/src/main.c index 47b72e2cdd2b9d1f0dc3840637b4f0cc0405337f..97522476ff5ee00726bc7b574c4c32e06bc04bb4 100644 --- a/src/main.c +++ b/src/main.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: main.c,v 1.80 1999/12/13 04:58:53 per Exp $"); +RCSID("$Id: main.c,v 1.81 2000/03/07 21:23:41 hubbe Exp $"); #include "fdlib.h" #include "backend.h" #include "module.h" @@ -611,6 +611,7 @@ void low_exit_main(void) { INT32 num,size,recount=0; fprintf(stderr,"Exited normally, counting bytes.\n"); + search_all_memheaders_for_references(); count_memory_in_arrays(&num, &size); if(num) diff --git a/src/pike_memory.c b/src/pike_memory.c index 52c930f671321dbabf1ab014f8b9810a5c857ce7..7a8b852e7757388f06dc8990fa90a4e708085b6a 100644 --- a/src/pike_memory.c +++ b/src/pike_memory.c @@ -10,7 +10,7 @@ #include "pike_macros.h" #include "gc.h" -RCSID("$Id: pike_memory.c,v 1.52 2000/02/03 19:09:12 grubba Exp $"); +RCSID("$Id: pike_memory.c,v 1.53 2000/03/07 21:23:42 hubbe Exp $"); /* strdup() is used by several modules, so let's provide it */ #ifndef HAVE_STRDUP @@ -691,11 +691,22 @@ int verbose_debug_malloc = 0; int verbose_debug_exit = 1; int debug_malloc_check_all = 0; +/* #define DMALLOC_PROFILE */ +#define DMALLOC_AD_HOC + +#ifdef DMALLOC_AD_HOC +/* A gigantic size (16Mb) will help a lot in AD_HOC mode */ +#define LHSIZE 4100011 +#else #define LHSIZE 1109891 -#define FLSIZE 8803 +#endif + +#define FLSIZE 43391 #define DEBUG_MALLOC_PAD 32 #define FREE_DELAY 4096 #define MAX_UNFREE_MEM 1024*1024*32 +#define RNDSIZE 1777 /* A small size will help keep it in the cache */ +#define AD_HOC_CHECK_INTERVAL 620 * 10 static void *blocks_to_free[FREE_DELAY]; static unsigned int blocks_to_free_ptr=0; @@ -734,27 +745,45 @@ struct memhdr struct memhdr *next; long size; int flags; +#ifdef DMALLOC_AD_HOC + int misses; +#endif void *data; struct memloc *locations; }; static struct fileloc *flhash[FLSIZE]; static struct memloc *mlhash[LHSIZE]; +static char rndbuf[RNDSIZE + DEBUG_MALLOC_PAD*2]; static struct memhdr no_leak_memlocs; static int file_location_number=10; static int loc_accepted_leak=0; static int loc_referenced=0; +static int memheader_references_located=0; + + +#ifdef DMALLOC_PROFILE +static int add_location_calls=0; +static int add_location_seek=0; +static int add_location_new=0; +static int add_location_cache_hits=0; +static int add_location_duplicate=0; /* Used in AD_HOC mode */ +#endif #if DEBUG_MALLOC_PAD - 0 > 0 char *do_pad(char *mem, long size) { - long q,e; + unsigned long q,e; mem+=DEBUG_MALLOC_PAD; q= (((long)mem) ^ 0x555555) + (size * 9248339); /* fprintf(stderr,"Padding %p(%d) %ld\n",mem, size, q); */ #if 1 + q%=RNDSIZE; + MEMCPY(mem - DEBUG_MALLOC_PAD, rndbuf+q, DEBUG_MALLOC_PAD); + MEMCPY(mem + size, rndbuf+q, DEBUG_MALLOC_PAD); +#else for(e=0;e< DEBUG_MALLOC_PAD; e+=4) { char tmp; @@ -781,7 +810,7 @@ char *do_pad(char *mem, long size) void check_pad(struct memhdr *mh, int freeok) { static int out_biking=0; - long q,e; + unsigned long q,e; char *mem=mh->data; long size=mh->size; if(out_biking) return; @@ -802,6 +831,25 @@ void check_pad(struct memhdr *mh, int freeok) /* fprintf(stderr,"Checking %p(%d) %ld\n",mem, size, q); */ #if 1 + q%=RNDSIZE; + if(MEMCMP(mem - DEBUG_MALLOC_PAD, rndbuf+q, DEBUG_MALLOC_PAD)) + { + out_biking=1; + fprintf(stderr,"Pre-padding overwritten for " + "block at %p (size %ld)!\n", mem, size); + describe(mem); + abort(); + } + + if(MEMCMP(mem + size, rndbuf+q, DEBUG_MALLOC_PAD)) + { + out_biking=1; + fprintf(stderr,"Pre-padding overwritten for " + "block at %p (size %ld)!\n", mem, size); + describe(mem); + abort(); + } +#else for(e=0;e< DEBUG_MALLOC_PAD; e+=4) { char tmp; @@ -1011,7 +1059,7 @@ static int find_location(struct memhdr *mh, int locnum) static void add_location(struct memhdr *mh, int locnum) { - struct memloc *ml; + struct memloc *ml=0; unsigned long l; #ifndef __NT__ @@ -1023,31 +1071,120 @@ static void add_location(struct memhdr *mh, int locnum) if(find_location(&no_leak_memlocs, locnum)) return; #endif +#ifdef DMALLOC_PROFILE + add_location_calls++; +#endif + l=lhash(mh,locnum); if(mlhash[l] && mlhash[l]->mh==mh && mlhash[l]->locnum==locnum) { mlhash[l]->times++; +#ifdef DMALLOC_PROFILE + add_location_cache_hits++; +#endif return; } +#ifdef DMALLOC_AD_HOC + if(mh->misses > AD_HOC_CHECK_INTERVAL) + { + unsigned long l2; + struct memloc **prev=&mh->locations; + while((ml=*prev)) + { +#ifdef DMALLOC_PROFILE + add_location_seek++; +#endif + if(ml->locnum == locnum) + break; + + l2=lhash(mh, ml->locnum); + + if(mlhash[l2] && mlhash[l2]!=ml && + mlhash[l2]->mh == mh && mlhash[l2]->locnum == ml->locnum) + { + /* We found a duplicate */ +#ifdef DMALLOC_PROFILE + add_location_duplicate++; +#endif + mlhash[l2]->times+=ml->times; + *prev=ml->next; + really_free_memloc(ml); + }else{ + prev=&ml->next; + } + } + if(!ml) mh->misses=0; + } +#else for(ml=mh->locations;ml;ml=ml->next) + { +#ifdef DMALLOC_PROFILE + add_location_seek++; +#endif if(ml->locnum==locnum) break; + } +#endif if(!ml) { +#ifdef DMALLOC_PROFILE + add_location_new++; +#endif ml=alloc_memloc(); ml->times=0; ml->locnum=locnum; ml->next=mh->locations; ml->mh=mh; mh->locations=ml; + +#ifdef DMALLOC_AD_HOC + mh->misses++; +#endif + } ml->times++; mlhash[l]=ml; } +static void remove_location(struct memhdr *mh, int locnum) +{ + struct memloc *ml,**prev; + unsigned long l; + +#ifndef __NT__ + if(!mt_trylock(& debug_malloc_mutex)) + fatal("remove_location running unlocked!\n"); +#endif + +#if DEBUG_MALLOC - 0 < 2 + if(find_location(&no_leak_memlocs, locnum)) return; +#endif + + l=lhash(mh,locnum); + + if(mlhash[l] && mlhash[l]->mh==mh && mlhash[l]->locnum==locnum) + mlhash[l]=0; + + + prev=&mh->locations; + while((ml=*prev)) + { + if(ml->locnum==locnum) + { + *prev=ml->next; + really_free_memloc(ml); +#ifndef DMALLOC_AD_HOC + break; +#endif + }else{ + prev=&ml->next; + } + } +} + int dmalloc_default_location=0; static struct memhdr *low_make_memhdr(void *p, int s, int locnum) @@ -1268,6 +1405,31 @@ void dump_memhdr_locations(struct memhdr *from, void debug_malloc_dump_references(void *x) { + struct memhdr *mh=my_find_memhdr(x,0); + if(!mh) return; + if(memheader_references_located) + { + int referenced=0; + struct memloc *l; + + for(l=mh->locations;l;l=l->next) + { + if(l->locnum == loc_accepted_leak) referenced|=2; + if(l->locnum == loc_referenced) referenced|=1; + } + if(referenced & 2) + { + fprintf(stderr,"<<<This leak has been ignored>>>\n"); + } + else if(referenced & 1) + { + fprintf(stderr,"<<<Possibly referenced>>>\n"); + } + else + { + fprintf(stderr,"<<<=- No known references to this block -=>>>\n"); + } + } dump_memhdr_locations(my_find_memhdr(x,0),0); } @@ -1309,6 +1471,45 @@ void list_open_fds(void) mt_unlock(&debug_malloc_mutex); } +static void low_search_all_memheaders_for_references(void) +{ + unsigned long h; + struct memhdr *m; + + for(h=0;h<(unsigned long)memhdr_hash_table_size;h++) + for(m=memhdr_hash_table[h];m;m=m->next) + remove_location(m, loc_referenced); + + for(h=0;h<(unsigned long)memhdr_hash_table_size;h++) + { + for(m=memhdr_hash_table[h];m;m=m->next) + { + unsigned int e; + struct memhdr *tmp; + void **p=m->data; + + if( ! ((sizeof(void *)-1) & (long) p )) + { + if(m->size > 0) + { + for(e=0;e<m->size/sizeof(void *);e++) + if((tmp=find_memhdr(p[e]))) + add_location(tmp, loc_referenced); + } + } + } + } + + memheader_references_located=1; +} + +void search_all_memheaders_for_references(void) +{ + mt_lock(&debug_malloc_mutex); + low_search_all_memheaders_for_references(); + mt_unlock(&debug_malloc_mutex); +} + void cleanup_memhdrs(void) { unsigned long h; @@ -1328,24 +1529,7 @@ void cleanup_memhdrs(void) if(verbose_debug_exit) { int first=1; - for(h=0;h<(unsigned long)memhdr_hash_table_size;h++) - { - struct memhdr *m; - for(m=memhdr_hash_table[h];m;m=m->next) - { - unsigned int e; - struct memhdr *tmp; - void **p=m->data; - - if( ! ((sizeof(void *)-1) & (long) p )) - { - for(e=0;e<m->size/sizeof(void *);e++) - if((tmp=find_memhdr(p[e]))) - add_location(tmp, loc_referenced); - } - } - } - + low_search_all_memheaders_for_references(); for(h=0;h<(unsigned long)memhdr_hash_table_size;h++) { @@ -1415,6 +1599,30 @@ void cleanup_memhdrs(void) } } } + + +#ifdef DMALLOC_PROFILE + { + INT32 num,mem; + + fprintf(stderr,"add_location %d cache %d (%3.3f%%) new: %d (%3.3f%%)\n", + add_location_calls, + add_location_cache_hits, + add_location_cache_hits*100.0/add_location_calls, + add_location_new, + add_location_new*100.0/add_location_calls); + fprintf(stderr," seek: %3.7f duplicates: %d\n", + ((double)add_location_seek)/(add_location_calls-add_location_cache_hits), + add_location_duplicate); + + count_memory_in_memhdrs(&num,&mem); + fprintf(stderr,"memhdrs: %8ld, %10ld bytes\n",(long)num,(long)mem); + + count_memory_in_filelocs(&num,&mem); + fprintf(stderr,"filelocs: %8ld, %10ld bytes\n",(long)num,(long)mem); + } +#endif + } mt_unlock(&debug_malloc_mutex); mt_destroy(&debug_malloc_mutex); @@ -1435,8 +1643,11 @@ static void unlock_da_lock(void) int main(int argc, char *argv[]) { + int e; extern int dbm_main(int, char **); + for(e=0;e<NELEM(rndbuf);e++) rndbuf[e]= (rand() % 511) | 1; + #if DEBUG_MALLOC_PAD & 3 fprintf(stderr,"DEBUG_MALLOC_PAD not dividable by four!\n"); exit(99);