There was a design flaw that caused a crash on windows and
authorlego <lego@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 20 Mar 2005 00:19:15 +0000 (00:19 +0000)
committerlego <lego@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 20 Mar 2005 00:19:15 +0000 (00:19 +0000)
left uninitialized successive copies of the stats tree.

Split the stats_tree data in two different structs one for data that's
always needed and it's not going to change at every run and another
for each run of the tap.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@13816 f5534014-38df-0310-8fa8-9805f1628bb7

epan/stats_tree.c
epan/stats_tree_priv.h
gtk/stats_tree_stat.c
tap-stats_tree.c

index 5d08a49a58af46feae5aa3fbf396aa53e4a023cb..5bc9899595a3f153cd9861878eb1fa151a6ebc9d 100644 (file)
@@ -150,7 +150,7 @@ static void free_stat_node( stat_node* node ) {
                        free_stat_node(child);
        }
        
-       if(node->st->free_node_pr) node->st->free_node_pr(node);
+       if(node->st->cfg->free_node_pr) node->st->cfg->free_node_pr(node);
        
        if (node->hash) g_hash_table_destroy(node->hash);
 
@@ -161,19 +161,19 @@ static void free_stat_node( stat_node* node ) {
        g_free(node);
 }
 
-/* destroys the whole tree */
+/* destroys the whole tree instance */
 extern void free_stats_tree(stats_tree* st) {
        stat_node* child;
        
-       g_free(st->tapname);
-       g_free(st->abbr);
        g_free(st->filter);
+       g_hash_table_destroy(st->names);
+       g_ptr_array_free(st->parents,FALSE);
        
        for (child = st->root.children; child; child = child->next ) 
                free_stat_node(child);
        
-       if (st->free_tree_pr)
-               st->free_tree_pr(st);
+       if (st->cfg->free_tree_pr)
+               st->cfg->free_tree_pr(st);
                        
        g_free(st);
 }
@@ -190,8 +190,8 @@ static void reset_stat_node(stat_node* node) {
        
        node->counter = 0;
        
-       if(node->st->reset_node) {
-               node->st->reset_node(node);
+       if(node->st->cfg->reset_node) {
+               node->st->cfg->reset_node(node);
        }
        
 }
@@ -201,8 +201,8 @@ extern void reset_stats_tree(void* p) {
        stats_tree* st = p;
        reset_stat_node(&st->root);
        
-       if (st->reset_tree) {
-               st->reset_tree(st);
+       if (st->cfg->reset_tree) {
+               st->cfg->reset_tree(st);
        }
 }
 
@@ -217,8 +217,8 @@ extern void reinit_stats_tree(void* p) {
        st->root.children = NULL;
        st->root.counter = 0;
        
-       if (st->init) {
-               st->init(st);
+       if (st->cfg->init) {
+               st->cfg->init(st);
        }
 }
 
@@ -229,18 +229,49 @@ extern void register_stats_tree(guint8* tapname,
                                                                stat_tree_packet_cb packet,
                                                                stat_tree_init_cb init ) {
        
-       stats_tree* st = g_malloc( sizeof(stats_tree) );
+       stats_tree_cfg* cfg = g_malloc( sizeof(stats_tree_cfg) );
 
        /* at the very least the abbrev and the packet function should be given */ 
        g_assert( tapname && abbr && packet );
 
-       st->tapname = g_strdup(tapname);
-       st->abbr = g_strdup(abbr);
-       st->name = name ? g_strdup(name) : g_strdup(abbr);
-       st->filter = NULL;
+       cfg->tapname = g_strdup(tapname);
+       cfg->abbr = g_strdup(abbr);
+       cfg->name = name ? g_strdup(name) : g_strdup(abbr);
        
+       cfg->packet = packet;
+       cfg->init = init;
+       
+       /* these have to be filled in by implementations */
+       cfg->setup_node_pr = NULL;
+       cfg->new_tree_pr = NULL;
+       cfg->free_node_pr = NULL;
+       cfg->free_tree_pr = NULL;
+       cfg->draw_node = NULL;
+       cfg->draw_tree = NULL;
+       cfg->reset_node = NULL;
+       cfg->reset_tree = NULL;
+
+       if (!registry) registry = g_hash_table_new(g_str_hash,g_str_equal);
+
+       g_hash_table_insert(registry,cfg->abbr,cfg);
+       
+}
+
+extern stats_tree* new_stats_tree(stats_tree_cfg* cfg, tree_pres* pr,char* filter) {
+       stats_tree* st = g_malloc(sizeof(stats_tree));
+
+       st->cfg = cfg;
+       st->pr = pr;
+
+       st->names = g_hash_table_new(g_str_hash,g_str_equal);
+       st->parents = g_ptr_array_new();
+       st->filter = filter;
+       
+       st->start = -1.0;
+       st->elapsed = 0.0;
+
        st->root.counter = 0;
-       st->root.name = g_strdup(name);
+       st->root.name = g_strdup(cfg->name);
        st->root.st = st;
        st->root.parent = NULL;
        st->root.children = NULL;
@@ -248,32 +279,10 @@ extern void register_stats_tree(guint8* tapname,
        st->root.hash = NULL;
        st->root.pr = NULL;
        
-       st->names = g_hash_table_new(g_str_hash,g_str_equal);
-       st->parents = g_ptr_array_new();
-       
        g_ptr_array_add(st->parents,&st->root);
        
-       st->start = -1.0;
-       st->elapsed = 0.0;
-       
-       st->packet = packet;
-       st->init = init;
-       
-       /* these have to be filled in by implementations */
-       st->setup_node_pr = NULL;
-       st->new_tree_pr = NULL;
-       st->free_node_pr = NULL;
-       st->free_tree_pr = NULL;
-       st->draw_node = NULL;
-       st->draw_tree = NULL;
-       st->reset_node = NULL;
-       st->reset_tree = NULL;
-
-       if (!registry) registry = g_hash_table_new(g_str_hash,g_str_equal);
-
-       g_hash_table_insert(registry,st->abbr,st);
-       
-}
+       return st;
+}      
 
 /* will be the tap packet cb */
 extern int stats_tree_packet(void* p, packet_info* pinfo, epan_dissect_t *edt, const void *pri) {
@@ -285,8 +294,8 @@ extern int stats_tree_packet(void* p, packet_info* pinfo, epan_dissect_t *edt, c
        
        st->elapsed = now - st->start;
        
-       if (st->packet)
-               return st->packet(st,pinfo,edt,pri);
+       if (st->cfg->packet)
+               return st->cfg->packet(st,pinfo,edt,pri);
        else
                return 0;
 }
@@ -295,12 +304,12 @@ extern GHashTable* stat_tree_registry(void) {
        return registry;
 }
 
-extern stats_tree* get_stats_tree_by_abbr(guint8* abbr) {
+extern stats_tree_cfg* get_stats_tree_by_abbr(guint8* abbr) {
        return g_hash_table_lookup(registry,abbr);
 }
 
 
-struct _stats_tree_pres_stuff {
+struct _stats_tree_pres_cbs {
        void (*setup_node_pr)(stat_node*);
        void (*free_node_pr)(stat_node*);
        void (*draw_node)(stat_node*);
@@ -312,17 +321,17 @@ struct _stats_tree_pres_stuff {
 };
 
 static void setup_tree_presentation(gpointer k _U_, gpointer v, gpointer p) {
-       stats_tree* st = v;
-       struct _stats_tree_pres_stuff *d = p;
-       
-       st->setup_node_pr = d->setup_node_pr;
-       st->new_tree_pr = d->new_tree_pr;
-       st->free_node_pr = d->free_node_pr;
-       st->free_tree_pr = d->free_tree_pr;
-       st->draw_node = d->draw_node;
-       st->draw_tree = d->draw_tree;
-       st->reset_node = d->reset_node;
-       st->reset_tree = d->reset_tree;
+       stats_tree_cfg* cfg = v;
+       struct _stats_tree_pres_cbs *d = p;
+       
+       cfg->setup_node_pr = d->setup_node_pr;
+       cfg->new_tree_pr = d->new_tree_pr;
+       cfg->free_node_pr = d->free_node_pr;
+       cfg->free_tree_pr = d->free_tree_pr;
+       cfg->draw_node = d->draw_node;
+       cfg->draw_tree = d->draw_tree;
+       cfg->reset_node = d->reset_node;
+       cfg->reset_tree = d->reset_tree;
        
 }
 
@@ -336,7 +345,7 @@ extern void stats_tree_presentation(void (*registry_iterator)(gpointer,gpointer,
                                                                        void (*draw_tree)(stats_tree*),
                                                                        void (*reset_tree)(stats_tree*),
                                                                        void* data) {
-       struct _stats_tree_pres_stuff d = {setup_node_pr,free_node_pr,draw_node,reset_node,new_tree_pr,free_tree_pr,draw_tree,reset_tree};
+       struct _stats_tree_pres_cbs d = {setup_node_pr,free_node_pr,draw_node,reset_node,new_tree_pr,free_tree_pr,draw_tree,reset_tree};
        
        if (registry) g_hash_table_foreach(registry,setup_tree_presentation,&d);
        
@@ -407,15 +416,15 @@ static stat_node*  new_stat_node(stats_tree* st,
                g_hash_table_insert(node->parent->hash,node->name,node);
        }
        
-       if (st->setup_node_pr) {
-               st->setup_node_pr(node);
+       if (st->cfg->setup_node_pr) {
+               st->cfg->setup_node_pr(node);
        } else {
                node->pr = NULL;
        }
        
        return node;
 }
-
+/***/
 
 extern int create_node(stats_tree* st, const gchar* name, int parent_id, gboolean with_hash) {
        stat_node* node = new_stat_node(st,name,parent_id,with_hash,TRUE);
@@ -527,13 +536,14 @@ extern int create_range_node(stats_tree* st,
        return rng_root->id;
 }
 
+/****/
 extern int get_parent_id_by_name(stats_tree* st, const gchar* parent_name) {
        stat_node* node = g_hash_table_lookup(st->names,parent_name);
        
        if (node)
                return node->id;
        else
-               return 0; /* ??? -1 ??? */
+               return 0; /* XXX: this is the root shoud we return -1 instead?*/
 }
 
 
index 950c4bc1f5bdf7f3d3f752b241b2c26fc7dc734b..078d343a602494290e7ab1218a14c0a80c3da5f5 100644 (file)
  * as well as some operations on it */
 typedef struct _st_node_pres st_node_pres;
 
-/* implementations should define this to contain its own tree related data
+/* implementations should define this to contain its own dynamic tree related data
 * as well as some operations on it */
 typedef struct _tree_pres tree_pres;
 
-typedef struct _stat_node stat_node;
+/* implementations should define this to contain its own static tree related data
+* as well as some operations on it */
+typedef struct _tree_cfg_pres tree_cfg_pres;
 
 
+typedef struct _stat_node stat_node;
+typedef struct _stats_tree_cfg stats_tree_cfg;
+
 typedef struct _range_pair {
        gint floor;
        gint ceil;
@@ -58,7 +63,7 @@ struct _stat_node {
        GHashTable*             hash;
        
        /* the owner of this node */
-       stats_tree*             st;
+       stats_tree*     st;
        
        /* relatives */
        stat_node*      parent;
@@ -70,44 +75,52 @@ struct _stat_node {
        
        /* node presentation data */
        st_node_pres* pr;
-} ;
+};
 
 struct _stats_tree {
-       guint8*                 abbr;
-       guint8*                 name;
-       guint8*                 tapname;
+       /* the "class" from which it's derived */
+       stats_tree_cfg* cfg;
        
        char*                   filter;
        
        /* times */
        float                   start;
        float                   elapsed;
-               
 
-          /* used to lookup named parents:
-               *    key: parent node name
-               *  value: parent node
-               */
+   /* used to lookup named parents:
+       *    key: parent node name
+       *  value: parent node
+       */
        GHashTable*                     names;
        
-          /* used for quicker lookups of parent nodes */
+   /* used for quicker lookups of parent nodes */
        GPtrArray*                      parents;
+               
+       /*
+        *  tree representation
+        *      to be defined (if needed) by the implementations
+        */
+       tree_pres* pr;
        
        /* every tree in nature has one */
        stat_node       root;
+};
+
+struct _stats_tree_cfg {
+       guint8*                 abbr;
+       guint8*                 name;
+       guint8*                 tapname;
+       
        
        /* dissector defined callbacks */
        stat_tree_packet_cb packet;
        stat_tree_init_cb init;
 
-       /**** tree representation
-        *      to be defined (if needed) by the implementations
-        */
-       tree_pres* pr;
        
-       /*  node presentation callbacks
+       /*
+        * node presentation callbacks
         */
-               
+
        /* last to be called at node creation */
        void (*setup_node_pr)(stat_node*);
        
@@ -118,7 +131,11 @@ struct _stats_tree {
        void (*draw_node)(stat_node*);
        void (*reset_node)(stat_node*);
        
-       /* tree presentation callbacks */
+       /*
+        * tree presentation callbacks
+        */
+       tree_cfg_pres* pr;
+       
        
        tree_pres* (*new_tree_pr)(stats_tree*);
        void (*free_tree_pr)(stats_tree*);
@@ -138,6 +155,8 @@ extern void stats_tree_presentation(void (*registry_iterator)(gpointer,gpointer,
                                                                        void (*reset_tree)(stats_tree*),
                                                                        void* data);
 
+extern stats_tree* new_stats_tree(stats_tree_cfg* cfg, tree_pres* pr, char* filter);
+
 /* callback for taps */
 extern int  stats_tree_packet(void*, packet_info*, epan_dissect_t*, const void *);
 
@@ -155,7 +174,7 @@ extern void free_stats_tree(stats_tree* st);
 extern guint8* get_st_abbr(const guint8* optarg);
 
 /* obtains a stats tree from the registry given its abbr */
-extern stats_tree* get_stats_tree_by_abbr(guint8* abbr);
+extern stats_tree_cfg* get_stats_tree_by_abbr(guint8* abbr);
 
 /* extracts node data as strings from a stat_node into
    the buffers given by value, rate and precent
index 2cf0dbf955cc0f1cbdb533847e2b15d8b4128286..968b48395d1fc528abdf3a49b3169880f8ef9d98 100644 (file)
@@ -57,9 +57,11 @@ struct _st_node_pres {
 #endif
 };
 
+struct _tree_cfg_pres {
+       tap_dfilter_dlg* stat_dlg;
+};
 
 struct _tree_pres {
-       tap_dfilter_dlg* stat_dlg;
        GString*                text;
        GtkWidget*              win;
        
@@ -187,6 +189,9 @@ static void free_gtk_tree(GtkWindow *win _U_, stats_tree *st)
        if (st->root.pr)
                st->root.pr->iter = NULL;
 #endif
+       
+       free_stats_tree(st);
+       
 }
 
 
@@ -194,6 +199,8 @@ static void free_gtk_tree(GtkWindow *win _U_, stats_tree *st)
 static void init_gtk_tree(char* optarg) {
        guint8* abbr = get_st_abbr(optarg);
        stats_tree* st = NULL;
+       stats_tree_cfg* cfg = NULL;
+       tree_pres* pr = g_malloc(sizeof(tree_pres));
        guint8* title = NULL;
        guint8* window_name = NULL;
        GString* error_string;
@@ -206,20 +213,20 @@ static void init_gtk_tree(char* optarg) {
 #endif
        
        if (abbr) {
-               st = get_stats_tree_by_abbr(abbr);
+               cfg = get_stats_tree_by_abbr(abbr);
                
-               if (st != NULL) {
-                       init_strlen = strlen(st->pr->stat_dlg->init_string);
+               if (cfg != NULL) {
+                       init_strlen = strlen(cfg->pr->stat_dlg->init_string);
                        
-                       if (strncmp (optarg, st->pr->stat_dlg->init_string, init_strlen) == 0){
+                       if (strncmp (optarg, cfg->pr->stat_dlg->init_string, init_strlen) == 0){
                                if (init_strlen == strlen(optarg)) {
-                                       st->filter= "";
+                                       st = new_stats_tree(cfg,pr,NULL);
                                } else { 
-                                       st->filter=((guint8*)optarg)+init_strlen+1;
+                                       st = new_stats_tree(cfg,pr,((guint8*)optarg)+init_strlen+1);
                                }
                                
                        } else {
-                               st->filter=NULL;
+                               st = new_stats_tree(cfg,pr,NULL);
                        }
                } else {
                        g_error("no such stats_tree (%s) found in stats_tree registry",abbr);
@@ -229,18 +236,18 @@ static void init_gtk_tree(char* optarg) {
        } else {
                g_error("could not obtain stats_tree abbr from optarg");                
        }
-       
-       window_name = g_strdup_printf("%s Stats Tree", st->name);
+
+       window_name = g_strdup_printf("%s Stats Tree", cfg->name);
        
        st->pr->win = window_new_with_geom(GTK_WINDOW_TOPLEVEL,window_name,window_name);
        gtk_window_set_default_size(GTK_WINDOW(st->pr->win), 400, 400);
        g_free(window_name);
     
        if(st->filter){
-               title=g_strdup_printf("%s with filter: %s",st->name,st->filter);
+               title=g_strdup_printf("%s with filter: %s",cfg->name,st->filter);
        } else {
                st->filter=NULL;
-               title=g_strdup_printf("%s", st->name);
+               title=g_strdup_printf("%s", cfg->name);
        }
        
     gtk_window_set_title(GTK_WINDOW(st->pr->win), title);
@@ -302,7 +309,7 @@ static void init_gtk_tree(char* optarg) {
        gtk_container_add( GTK_CONTAINER(main_vb), scr_win);
 #endif
        
-       error_string = register_tap_listener( st->tapname,
+       error_string = register_tap_listener( cfg->tapname,
                                                                                  st,
                                                                                  st->filter,
                                                                                  NULL,
@@ -313,7 +320,7 @@ static void init_gtk_tree(char* optarg) {
                /* error, we failed to attach to the tap. clean up */
                simple_dialog( ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str );
                /* destroy_stat_tree_window(st); */
-               g_error("stats_tree for: %s failed to attach to the tap: %s",st->name,error_string->str);
+               g_error("stats_tree for: %s failed to attach to the tap: %s",cfg->name,error_string->str);
                g_string_free(error_string, TRUE);
        }
                
@@ -334,45 +341,35 @@ static void init_gtk_tree(char* optarg) {
        gtk_tree_view_set_model(GTK_TREE_VIEW(st->pr->tree),GTK_TREE_MODEL(st->pr->store));
 #endif
        
-       if (st->filter) {
-               reinit_stats_tree(st);
-       } else {
-               st->init(st);
-       }
+       st->cfg->init(st);
 
        cf_retap_packets(&cfile);
-       
 }
 
 
 static void register_gtk_stats_tree_tap (gpointer k _U_, gpointer v, gpointer p _U_) {
-       stats_tree* st = v;
+       stats_tree_cfg* cfg = v;
        guint8* s;
 
-       s = g_strdup_printf("%s,tree",st->abbr);
+       s = g_strdup_printf("%s,tree",cfg->abbr);
        
        register_ethereal_tap(s, init_gtk_tree);
        
-       st->pr = g_malloc(sizeof(tree_pres));
-       st->pr->text = NULL;
-       st->pr->win = NULL;
-       
-#if GTK_MAJOR_VERSION >= 2
-       st->pr->store = NULL;
-       st->pr->tree = NULL;
-#else
-       st->pr->textbox = NULL;
-#endif
+       cfg->pr = g_malloc(sizeof(tree_pres));
        
-       st->pr->stat_dlg = g_malloc(sizeof(tap_dfilter_dlg));
+       cfg->pr->stat_dlg = g_malloc(sizeof(tap_dfilter_dlg));
        
-       st->pr->stat_dlg->win_title = g_strdup_printf("%s Stats Tree",st->name);
-       st->pr->stat_dlg->init_string = g_strdup_printf("%s,tree",st->abbr);
-       st->pr->stat_dlg->tap_init_cb = init_gtk_tree;
-       st->pr->stat_dlg->index = -1;
+       cfg->pr->stat_dlg->win_title = g_strdup_printf("%s Stats Tree",cfg->name);
+       cfg->pr->stat_dlg->init_string = g_strdup_printf("%s,tree",cfg->abbr);
+       cfg->pr->stat_dlg->tap_init_cb = init_gtk_tree;
+       cfg->pr->stat_dlg->index = -1;
        
-       register_tap_menu_item(st->name, REGISTER_TAP_GROUP_NONE,
-                                                  gtk_tap_dfilter_dlg_cb, NULL, NULL, st->pr->stat_dlg);
+       register_tap_menu_item(cfg->name, REGISTER_TAP_GROUP_NONE,
+                                                  gtk_tap_dfilter_dlg_cb, NULL, NULL, cfg->pr->stat_dlg);
+}
+
+static void free_tree_presentation(stats_tree* st) {
+       g_free(st->pr);
 }
 
 void
@@ -382,5 +379,5 @@ register_tap_listener_stats_tree_stat(void)
        stats_tree_presentation(register_gtk_stats_tree_tap,
                                                        setup_gtk_node_pr, NULL,
                                                        NULL,
-                                                       NULL, NULL, NULL, NULL, NULL, NULL);
+                                                       NULL, NULL, free_tree_presentation, NULL, NULL, NULL);
 }
index 2c85abcd92ed3382e13ff0f2b3aa319d4094d436..4c0f3a1925961a0dfeb635292d37a77e7c9b0c0e 100644 (file)
@@ -37,8 +37,11 @@ struct _st_node_pres {
        void* dummy;
 };
 
-
 struct _tree_pres {
+       void* dummy;
+};
+
+struct _tree_cfg_pres {
        guint8* init_string;    
 };
 
@@ -50,7 +53,7 @@ static void draw_stats_tree(void *psp) {
        
        s = g_string_new("\n===================================================================\n");
        fmt = g_strdup_printf(" %%s%%-%us%%12s\t%%12s\t%%12s\n",stats_branch_max_name_len(&st->root,0));
-       g_string_sprintfa(s,fmt,"",st->name,"value","rate","percent");
+       g_string_sprintfa(s,fmt,"",st->cfg->name,"value","rate","percent");
        g_free(fmt);
        g_string_sprintfa(s,"-------------------------------------------------------------------\n");
        
@@ -67,14 +70,15 @@ static void draw_stats_tree(void *psp) {
 static void  init_stats_tree(char *optarg) {
        guint8* abbr = get_st_abbr(optarg);
        GString *error_string;
-       stats_tree *st = NULL;
-
+       stats_tree_cfg *cfg = NULL;
+       stats_tree* st = NULL;
+       
        if (abbr) {
-               st = get_stats_tree_by_abbr(abbr);
-               
-               if (st != NULL) {
-                       if (strncmp (optarg, st->pr->init_string, strlen(st->pr->init_string)) == 0){
-                               st->filter=((guint8*)optarg)+strlen(st->pr->init_string);
+               cfg = get_stats_tree_by_abbr(abbr);
+
+               if (cfg != NULL) {
+                       if (strncmp (optarg, cfg->pr->init_string, strlen(cfg->pr->init_string)) == 0){
+                               st = new_stats_tree(cfg,NULL,((guint8*)optarg)+strlen(cfg->pr->init_string));
                        } else {
                                st->filter=NULL;
                        }
@@ -88,7 +92,7 @@ static void  init_stats_tree(char *optarg) {
                g_error("could not obtain stats_tree abbr (%s) from optarg '%s'",abbr,optarg);          
        }
        
-       error_string = register_tap_listener( st->tapname,
+       error_string = register_tap_listener( st->cfg->tapname,
                                                                                  st,
                                                                                  st->filter,
                                                                                  reset_stats_tree,
@@ -96,28 +100,32 @@ static void  init_stats_tree(char *optarg) {
                                                                                  draw_stats_tree);
        
        if (error_string) {
-               g_error("stats_tree for: %s failed to attach to the tap: %s",st->name,error_string->str);
+               g_error("stats_tree for: %s failed to attach to the tap: %s",cfg->name,error_string->str);
        }
 
-       if (st->init) st->init(st);
+       if (cfg->init) cfg->init(st);
 
 }
 
 void register_stats_tree_tap (gpointer k _U_, gpointer v, gpointer p _U_) {
-       stats_tree* st = v;
+       stats_tree_cfg* cfg = v;
        
-       st->pr = g_malloc(sizeof(tree_pres));
-       st->pr->init_string = g_strdup_printf("%s,tree",st->abbr);
+       cfg->pr = g_malloc(sizeof(tree_cfg_pres));
+       cfg->pr->init_string = g_strdup_printf("%s,tree",cfg->abbr);
 
-       register_ethereal_tap(st->pr->init_string, init_stats_tree);
+       register_ethereal_tap(cfg->pr->init_string, init_stats_tree);
        
 }
 
+static void free_tree_presentation(stats_tree* st) {
+       g_free(st->pr);
+}
+
 
 void
 register_tap_listener_stats_tree_stat(void)
 {
        stats_tree_presentation(register_stats_tree_tap,
                                                        NULL, NULL, NULL, NULL, NULL,
-                                                       NULL, NULL, NULL, NULL);
+                                                       free_tree_presentation, NULL, NULL, NULL);
 }