123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820 |
- #include <string.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include "private.h"
- #include "context.h"
- #include "node.h"
- unsigned long lub_heap_frame_count;
- #define CONTEXT_CHUNK_SIZE 100 /* number of contexts per chunk */
- #define CONTEXT_MAX_CHUNKS 100 /* allow upto 10000 contexts */
- /*---------------------------------------------------------
- * PRIVATE META FUNCTIONS
- *--------------------------------------------------------- */
- void
- lub_heap_context_meta_init(void)
- {
- static bool_t initialised = BOOL_FALSE;
- if(BOOL_FALSE == initialised)
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- initialised = BOOL_TRUE;
- /* initialise the context tree */
- lub_bintree_init(&leak->m_context_tree,
- offsetof(lub_heap_context_t,bt_node),
- lub_heap_context_compare,
- lub_heap_context_getkey);
- lub_heap_leak_release(leak);
- }
- }
- /*--------------------------------------------------------- */
- int
- lub_heap_context_compare(const void *clientnode,
- const void *clientkey)
- {
- int i,delta=0;
- const lub_heap_context_t *node = clientnode;
- const lub_heap_context_key_t *key = clientkey;
- function_t * const *node_fn = node->key.backtrace;
- function_t * const *key_fn = key->backtrace;
-
- for(i = lub_heap_frame_count;
- i;
- --i,++node_fn,++key_fn)
- {
- delta = ((unsigned long)*node_fn - (unsigned long)*key_fn);
- if(0 != delta)
- {
- break;
- }
- }
- return delta;
- }
- /*--------------------------------------------------------- */
- /* we simply use the embedded key as the index */
- void
- lub_heap_context_getkey(const void *clientnode,
- lub_bintree_key_t *key)
- {
- const lub_heap_context_t * context = clientnode;
- memcpy(key,&context->key,sizeof(lub_heap_context_key_t));
- }
- /*--------------------------------------------------------- */
- static bool_t
- lub_heap_foreach_context(bool_t (*fn)(lub_heap_context_t *,void *),
- void *arg)
- {
- bool_t result = BOOL_FALSE;
- lub_heap_context_t * context;
- lub_bintree_iterator_t iter;
- lub_heap_context_meta_init();
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- for(context = lub_bintree_findfirst(&leak->m_context_tree),
- context ? lub_bintree_iterator_init(&iter,&leak->m_context_tree,context) : (void)0;
- context;
- context = lub_bintree_iterator_next(&iter))
- {
- lub_heap_leak_release(leak);
- /* invoke the specified method on this context */
- result = fn(context,arg);
- leak = lub_heap_leak_instance();
- }
- lub_heap_leak_release(leak);
- }
- return result;
- }
- /*--------------------------------------------------------- */
- static void
- lub_heap_show_summary(void)
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- size_t ok_allocs = leak->m_stats.allocs;
- size_t ok_bytes = leak->m_stats.alloc_bytes;
- size_t ok_overhead = leak->m_stats.alloc_overhead;
-
- ok_allocs -= leak->m_stats.partials;
- ok_allocs -= leak->m_stats.leaks;
-
- ok_overhead -= leak->m_stats.partial_overhead;
- ok_overhead -= leak->m_stats.leaked_overhead;
-
- printf("\n"
- " +----------+----------+----------+----------+\n");
- printf(" TOTALS | blocks| bytes| average| overhead|\n");
- printf("+---------+----------+----------+----------+----------+\n");
- printf("|contexts |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10s|\n",
- leak->m_stats.contexts,
- leak->m_stats.contexts * sizeof(lub_heap_context_t),
- leak->m_stats.contexts ? sizeof(lub_heap_context_t) : 0,
- "");
- printf("|allocs |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|\n",
- ok_allocs,
- ok_bytes,
- ok_allocs ? (ok_bytes / ok_allocs) : 0,
- ok_overhead);
- if(leak->m_stats.partials)
- {
- printf("|partials |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|\n",
- leak->m_stats.partials,
- leak->m_stats.partial_bytes,
- leak->m_stats.partials ? (leak->m_stats.partial_bytes / leak->m_stats.partials) : 0,
- leak->m_stats.partial_overhead);
- }
- if(leak->m_stats.leaks)
- {
- printf("|leaks |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|\n",
- leak->m_stats.leaks,
- leak->m_stats.leaked_bytes,
- leak->m_stats.leaks ? (leak->m_stats.leaked_bytes / leak->m_stats.leaks) : 0,
- leak->m_stats.leaked_overhead);
- }
- printf("+---------+----------+----------+----------+----------+\n");
- lub_heap_leak_release(leak);
- }
- /*--------------------------------------------------------- */
- /*---------------------------------------------------------
- * PRIVATE METHODS
- *--------------------------------------------------------- */
- static void
- lub_heap_context_foreach_node(lub_heap_context_t *this,
- void (*fn)(lub_heap_node_t *))
- {
- lub_heap_node_t * node;
-
- for(node = this->first_node;
- node;
- node = lub_heap_node__get_next(node))
- {
- /* invoke the specified method on this node */
- fn(node);
- }
- }
- /*--------------------------------------------------------- */
- /*---------------------------------------------------------
- * PUBLIC METHODS
- *--------------------------------------------------------- */
- void
- lub_heap_context_init(lub_heap_context_t * this,
- lub_heap_t * heap,
- const stackframe_t * stack)
- {
- lub_heap_context_meta_init();
-
- this->heap = heap;
- this->allocs = 0;
- this->alloc_bytes = 0;
- this->alloc_overhead = 0;
- this->leaks = 0;
- this->leaked_bytes = 0;
- this->leaked_overhead = 0;
- this->partials = 0;
- this->partial_bytes = 0;
- this->partial_overhead = 0;
- this->first_node = NULL;
-
- /* set the current backtrace for the context */
- this->key = *stack;
-
- /* intialise this context's binary tree node */
- lub_bintree_node_init(&this->bt_node);
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- /* add this context to the context_tree */
- lub_bintree_insert(&leak->m_context_tree,this);
- lub_heap_leak_release(leak);
- }
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_context_fini(lub_heap_context_t * this)
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- /* remove this node from the context_tree */
- lub_bintree_remove(&leak->m_context_tree,this);
- lub_heap_leak_release(leak);
- /* cleanup the context */
- lub_heap_context_clear(this);
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_context_insert_node(lub_heap_context_t * this,
- lub_heap_node_t * node)
- {
- /* add the node to the linked list */
- lub_heap_node__set_next(node,this->first_node);
- node->prev = NULL;
- if(this->first_node)
- {
- this->first_node->prev = node;
- }
- this->first_node = node;
-
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_context_remove_node(lub_heap_context_t *this,
- lub_heap_node_t *node)
- {
- lub_heap_node_t *next,*prev = NULL;
-
- /* remove the node from the context list */
- next = lub_heap_node__get_next(node);
- prev = node->prev;
- if(NULL == prev)
- {
- this->first_node = next;
- }
- else
- {
- lub_heap_node__set_next(prev,next);
- }
- if(NULL != next)
- {
- next->prev = prev;
- }
- /* clear the pointers */
- lub_heap_node__set_next(node,NULL);
- node->prev = NULL;
-
- /* is this the last node in a context? */
- if(0 == this->allocs)
- {
- /* removing the last node deletes the context */
- lub_heap_context_delete(this);
- }
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_context_show_frame(lub_heap_context_t * this,
- int frame)
- {
- if(frame >= 0)
- {
- long address = (long)this->key.backtrace[frame];
- if(address)
- {
- lub_heap_symShow(address);
- }
- }
- printf("\n");
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_node_post(lub_heap_node_t *node)
- {
- /* assume the worst */
- if(BOOL_TRUE == lub_heap_node__get_leaked(node))
- {
- /* this is a full leak */
- lub_heap_node__set_partial(node,BOOL_FALSE);
- }
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_node_prep(lub_heap_node_t *node,
- void *arg)
- {
- /* assume the worst */
- lub_heap_node__set_leaked(node,BOOL_TRUE);
- lub_heap_node__set_partial(node,BOOL_TRUE);
- lub_heap_node__set_scanned(node,BOOL_FALSE);
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_node_scan(lub_heap_node_t *node,
- void *arg)
- {
- /* only scan nodes which have references */
- if( (BOOL_FALSE == lub_heap_node__get_leaked(node) )
- && (BOOL_FALSE == lub_heap_node__get_scanned(node)) )
- {
- lub_heap_node__set_scanned(node,BOOL_TRUE);
- lub_heap_scan_memory(lub_heap_node__get_ptr(node),
- lub_heap_node__get_size(node));
- }
- }
- /*--------------------------------------------------------- */
- static bool_t
- lub_heap_context_prep(lub_heap_context_t *this,
- void *arg)
- {
- /* start off by assuming the worst */
- this->partials = this->leaks = this->allocs;
- this->partial_bytes = this->leaked_bytes = this->alloc_bytes;
- this->partial_overhead = this->leaked_overhead = this->alloc_overhead;
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- /* initialised the global stats */
- leak->m_stats.allocs += this->allocs;
- leak->m_stats.alloc_bytes += this->alloc_bytes;
- leak->m_stats.alloc_overhead += this->alloc_overhead;
- lub_heap_leak_release(leak);
- }
- return BOOL_TRUE;
- }
- /*--------------------------------------------------------- */
- static bool_t
- lub_heap_context_post(lub_heap_context_t *this,
- void *arg)
- {
- /* don't count full leaks as partials */
- this->partials -= this->leaks;
- this->partial_bytes -= this->leaked_bytes;
- this->partial_overhead -= this->leaked_overhead;
-
- /* post process the contained nodes */
- lub_heap_context_foreach_node(this,lub_heap_node_post);
- return BOOL_TRUE;
- }
- /*--------------------------------------------------------- */
- static void
- scan_segment(void *ptr,
- unsigned index,
- size_t size,
- void *arg)
- {
- lub_heap_segment_t *segment = ptr;
- const char *memory = (const char*)lub_heap_block_getfirst(segment);
-
- /* now scan the memory in this segment */
- printf(".");
- lub_heap_scan_memory(memory,size);
- }
- /*--------------------------------------------------------- */
- /**
- * This function scans all the nodes currently allocated in the
- * system for references to other allocated nodes.
- * First of all we mark all nodes as leaked, then scan all the nodes
- * for any references to other ones. If found those other ones
- * are cleared from being leaked.
- * At the end of the process all nodes which are leaked then
- * update their context leak count.
- */
- void
- lub_heap_scan_all(void)
- {
- lub_heap_t *heap;
- lub_heap_leak_t *leak = lub_heap_leak_instance();
-
- /* clear the summary stats */
- memset(&leak->m_stats,0,sizeof(leak->m_stats));
- lub_heap_leak_release(leak);
- /* first of all prepare the contexts for scanning */
- lub_heap_foreach_context(lub_heap_context_prep,0);
- /* then prepare all the nodes (including those who have no context) */
- lub_heap_foreach_node(lub_heap_node_prep,0);
-
- printf(" Scanning memory");
- /* clear out the stacks in the system */
- lub_heap_clean_stacks();
-
- /* Scan the current stack */
- printf(".");
- lub_heap_scan_stack();
-
- /* Scan the BSS segment */
- printf(".");
- lub_heap_scan_bss();
-
- /* Scan the DATA segment */
- printf(".");
- lub_heap_scan_data();
-
- /* Scan the non-monitored blocks which are allocated in the system */
- leak = lub_heap_leak_instance();
- for(heap = leak->m_heap_list;
- heap;
- heap = heap->next)
- {
- lub_heap_leak_release(leak);
- lub_heap_foreach_segment(heap,scan_segment,0);
- leak = lub_heap_leak_instance();
- }
- lub_heap_leak_release(leak);
-
- /*
- * now scan the nodes NB. only referenced nodes will be scanned
- * we loop until we stop scanning new nodes
- */
- leak = lub_heap_leak_instance();
- do
- {
- leak->m_stats.scanned = 0;
- /* scan each node */
- lub_heap_leak_release(leak);
- printf(".");
- lub_heap_foreach_node(lub_heap_node_scan,NULL);
- leak = lub_heap_leak_instance();
- } while(leak->m_stats.scanned);
-
- printf("done\n\n");
- /* post process each context and contained nodes */
- lub_heap_leak_release(leak);
- lub_heap_foreach_context(lub_heap_context_post,0);
- leak = lub_heap_leak_instance();
-
-
- lub_heap_leak_release(leak);
- }
- /*--------------------------------------------------------- */
- void lub_heap_node_show(lub_heap_node_t *node)
- {
- printf("%s%p[%"SIZE_FMT"] ",
- lub_heap_node__get_leaked(node) ? "*" : lub_heap_node__get_partial(node) ? "+" : "",
- lub_heap_node__get_ptr(node),
- lub_heap_node__get_size(node));
- }
- /*--------------------------------------------------------- */
- static bool_t
- lub_heap_context_match(lub_heap_context_t *this,
- const char *substring)
- {
- bool_t result = BOOL_TRUE;
- if(substring)
- {
- int i;
- long address;
- result = BOOL_FALSE;
- /*
- * search the stacktrace for this context
- * to see whether it matches
- */
- for(i = 0;
- (address = (long)this->key.backtrace[i]);
- ++i)
- {
- if(lub_heap_symMatch(address,substring))
- {
- result = BOOL_TRUE;
- break;
- }
- }
- }
- return result;
- }
- /*--------------------------------------------------------- */
- typedef struct
- {
- lub_heap_show_e how;
- const char *substring;
- } context_show_arg_t;
- /*--------------------------------------------------------- */
- bool_t
- lub_heap_context_show_fn(lub_heap_context_t *this,
- void *arg)
- {
- bool_t result = BOOL_FALSE;
- context_show_arg_t *show_arg = arg;
-
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- /* add in the context details */
- ++leak->m_stats.contexts;
- leak->m_stats.allocs += this->allocs;
- leak->m_stats.alloc_bytes += this->alloc_bytes;
- leak->m_stats.alloc_overhead += this->alloc_overhead;
- leak->m_stats.partials += this->partials;
- leak->m_stats.partial_bytes += this->partial_bytes;
- leak->m_stats.partial_overhead += this->partial_overhead;
- leak->m_stats.leaks += this->leaks;
- leak->m_stats.leaked_bytes += this->leaked_bytes;
- leak->m_stats.leaked_overhead += this->leaked_overhead;
- lub_heap_leak_release(leak);
-
-
- if(lub_heap_context_match(this,show_arg->substring))
- {
- result = lub_heap_context_show(this,show_arg->how);
- }
- return result;
- }
- /*--------------------------------------------------------- */
- bool_t
- lub_heap_context_show(lub_heap_context_t *this,
- lub_heap_show_e how)
- {
- long frame = lub_heap_frame_count-1;
- size_t ok_allocs = this->allocs;
- size_t ok_bytes = this->alloc_bytes;
- size_t ok_overhead = this->alloc_overhead;
-
- ok_allocs -= this->partials;
- ok_allocs -= this->leaks;
- ok_bytes -= this->partial_bytes;
- ok_bytes -= this->leaked_bytes;
- ok_overhead -= this->partial_overhead;
- ok_overhead -= this->leaked_overhead;
- switch(how)
- {
- case LUB_HEAP_SHOW_ALL:
- {
- /* show everything */
- break;
- }
- case LUB_HEAP_SHOW_PARTIALS:
- {
- if(0 < this->partials)
- {
- /* there's at least one partial in this context */
- break;
- }
- /*lint -e(616) fall through */
- }
- case LUB_HEAP_SHOW_LEAKS:
- {
- if(0 < this->leaks)
- {
- /* there's at least one leak in this context */
- break;
- }
- /*lint -e(616) fall through */
- }
- default:
- {
- /* nothing to be shown */
- return BOOL_FALSE;
- }
- }
- /* find the top of the stack trace */
- while((frame >= 0) && (0 == this->key.backtrace[frame]))
- {
- --frame;
- }
- printf(" +----------+----------+----------+----------+");
- lub_heap_context_show_frame(this,frame--);
- printf( "%10p| blocks| bytes| average| overhead|",(void*)this);
- lub_heap_context_show_frame(this,frame--);
- printf("+---------+----------+----------+----------+----------+");
- lub_heap_context_show_frame(this,frame--);
- printf("|allocs |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|",
- ok_allocs,
- ok_bytes,
- ok_allocs ? (ok_bytes / ok_allocs) : 0,
- ok_overhead);
- lub_heap_context_show_frame(this,frame--);
- if(this->partials)
- {
- printf("|partials |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|",
- this->partials,
- this->partial_bytes,
- this->partials ? (this->partial_bytes/this->partials) : 0,
- this->partial_overhead);
- lub_heap_context_show_frame(this,frame--);
- }
- if(this->leaks)
- {
- printf("|leaks |%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|%10"SIZE_FMT"|",
- this->leaks,
- this->leaked_bytes,
- this->leaks ? (this->leaked_bytes/this->leaks) : 0,
- this->leaked_overhead);
- lub_heap_context_show_frame(this,frame--);
- }
- printf("+---------+----------+----------+----------+----------+");
- lub_heap_context_show_frame(this,frame--);
- while(frame >= 0)
- {
- printf("%55s","");
- lub_heap_context_show_frame(this,frame--);
- }
- printf("ALLOCATED BLOCKS: ");
- /* now iterate the allocated nodes */
- lub_heap_context_foreach_node(this,lub_heap_node_show);
- printf("\n\n");
-
- return BOOL_TRUE;
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_context_clear(lub_heap_context_t *this)
- {
- /* should only ever get cleared when all nodes have left the context */
- assert(0 == this->first_node);
- this->heap = 0;
- /* reset the counters */
- this->allocs = 0;
- this->alloc_bytes = 0;
- this->leaks = 0;
- this->leaked_bytes = 0;
- this->partials = 0;
- this->partial_bytes = 0;
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_show_leak_trees(void)
- {
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- printf("context_tree : ");
- lub_bintree_dump(&leak->m_context_tree);
- printf("\n");
- printf("node_tree : ");
- lub_bintree_dump(&leak->m_node_tree);
- printf("\n");
- printf("clear_node_tree: ");
- lub_bintree_dump(&leak->m_clear_node_tree);
- printf("\n");
- lub_heap_leak_release(leak);
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_leak_scan(void)
- {
- if(0 < lub_heap_frame_count)
- {
- /* check for memory leaks */
- if(!lub_heap_is_tainting())
- {
- printf("******************************************"
- "*** Memory tainting is disabled so results\n"
- "*** of scan may miss some real leaks!\n"
- "******************************************\n\n");
- }
- lub_heap_scan_all();
- }
- else
- {
- printf("Leak detection currently disabled\n\n");
- }
- }
- /*--------------------------------------------------------- */
- bool_t
- lub_heap_leak_report(lub_heap_show_e how,
- const char *substring)
- {
- bool_t result = BOOL_FALSE;
-
- if(0 < lub_heap_frame_count)
- {
- bool_t bad_arg = BOOL_FALSE;
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- context_show_arg_t show_arg;
- show_arg.how = how;
- show_arg.substring = substring;
-
- /* zero these stats which will be accumulated from the contexts */
- leak->m_stats.contexts = 0;
- leak->m_stats.allocs = 0;
- leak->m_stats.alloc_bytes = 0;
- leak->m_stats.alloc_overhead = 0;
- leak->m_stats.partials = 0;
- leak->m_stats.partial_bytes = 0;
- leak->m_stats.partial_overhead = 0;
- leak->m_stats.leaks = 0;
- leak->m_stats.leaked_bytes = 0;
- leak->m_stats.leaked_overhead = 0;
- lub_heap_leak_release(leak);
-
- switch(how)
- {
- case LUB_HEAP_SHOW_LEAKS:
- case LUB_HEAP_SHOW_PARTIALS:
- case LUB_HEAP_SHOW_ALL:
- {
- result = lub_heap_foreach_context(lub_heap_context_show_fn,(void*)&show_arg);
- break;
- }
- default:
- {
- printf("Invalid argument: 0=leaks, 1=partials and leaks, 2=all allocations\n\n");
- bad_arg = BOOL_TRUE;
- break;
- }
- }
- if(BOOL_FALSE == bad_arg)
- {
- leak = lub_heap_leak_instance();
- if(leak->m_stats.leaks)
- {
- printf(" '*' = leaked memory\n");
- }
- if(leak->m_stats.partials)
- {
- printf(" '+' = partially leaked memory\n");
- }
- lub_heap_leak_release(leak);
- lub_heap_show_summary();
- printf(" %lu stack frames held for each allocation.\n\n",lub_heap_frame_count);
- }
- }
- else
- {
- printf("Leak detection currently disabled\n\n");
- }
- return result;
- }
- /*--------------------------------------------------------- */
- /*---------------------------------------------------------
- * PUBLIC META FUNCTIONS
- *--------------------------------------------------------- */
- void
- lub_heap__set_framecount(unsigned frames)
- {
- static bool_t clear_tainting_on_disable = BOOL_FALSE;
- lub_heap_leak_t *leak;
-
- if(frames == lub_heap_frame_count)
- return;
-
- /* iterate around clearing all the nodes in the node_tree */
- lub_heap_foreach_node(lub_heap_node_clear,0);
-
- leak = lub_heap_leak_instance();
- if(frames)
- {
- static bool_t registered = BOOL_FALSE;
- if(frames <= MAX_BACKTRACE)
- {
- /* change the number of frames held */
- lub_heap_frame_count = frames;
- }
- else
- {
- fprintf(stderr,"--- leak-detection frame count set to a maximum of %d\n",MAX_BACKTRACE);
- lub_heap_frame_count = MAX_BACKTRACE;
- }
- if(!lub_heap_is_tainting())
- {
- /* we need to taint memory to ensure old pointers don't mask leaks */
- clear_tainting_on_disable = BOOL_TRUE;
- lub_heap_taint(BOOL_TRUE);
- }
- if(BOOL_FALSE == registered)
- {
- registered = BOOL_TRUE;
- /*
- * set up the context pool
- */
- lub_dblockpool_init(&leak->m_context_pool,
- sizeof(lub_heap_context_t),
- CONTEXT_CHUNK_SIZE,
- CONTEXT_MAX_CHUNKS);
- }
- }
- else
- {
- /* switch off leak detection */
- lub_heap_frame_count = 0;
- if(clear_tainting_on_disable)
- {
- lub_heap_taint(BOOL_FALSE);
- clear_tainting_on_disable = BOOL_FALSE;
- }
- }
- lub_heap_leak_release(leak);
- }
- /*--------------------------------------------------------- */
- unsigned
- lub_heap__get_framecount(void)
- {
- return lub_heap_frame_count;
- }
- /*--------------------------------------------------------- */
- size_t
- lub_heap_context__get_instanceSize(void)
- {
- return (sizeof(lub_heap_context_t));
- }
- /*--------------------------------------------------------- */
- lub_heap_context_t *
- lub_heap_context_find(const stackframe_t *stack)
- {
- lub_heap_context_t *result;
- lub_heap_leak_t *leak = lub_heap_leak_instance();
- lub_heap_context_key_t key = *stack;
- result = lub_bintree_find(&leak->m_context_tree,&key);
- lub_heap_leak_release(leak);
- return result;
- }
- /*--------------------------------------------------------- */
|