git.haldean.org expel / 73b9d9c
value leak detection in gc Haldean Brown 6 years ago
1 changed file(s) with 57 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
3232 #include "expel/expel.h"
3333 #include "expel/gc.h"
3434 #include "expel/pointerset.h"
35 #include "expel/stream.h"
3536 #include "expel/uri.h"
3637 #include "expel/util.h"
3738 #include "expel/vector.h"
39 #include "expel/value.h"
3840
3941 static struct xl_gc_info *gc_stats;
4042
4143 static struct xl_vector graph_alloc = {0};
4244 static struct xl_vector graph_freed = {0};
45
46 static struct xl_vector value_alloc = {0};
47 static struct xl_vector value_freed = {0};
4348
4449 static struct xl_uri *graph_trace = NULL;
4550 static char *graph_trace_str = NULL;
106111 bool present;
107112 bool any_leaked;
108113 struct xl_dagc *graph;
114 struct xl_value *value;
109115 char *buf;
116 struct xl_stream s;
117
118 err = xl_stream_wfilep(&s, gc_out);
119 if (err != OK)
120 {
121 fprintf(gc_out, "couldn't open stream to gc output\n");
122 return;
123 }
110124
111125 fprintf(gc_out, "========================================\ngc stats:\n");
112 fprintf(gc_out, "alloc %lu pages, %lu freed, %ld remaining\n",
113 gc_stats->n_page_allocs,
114 gc_stats->n_page_frees,
115 (int64_t) gc_stats->n_page_allocs - gc_stats->n_page_frees);
116126 fprintf(gc_out, "alloc %lu vals, %lu freed, %ld remaining\n",
117127 gc_stats->n_val_allocs,
118128 gc_stats->n_val_frees,
147157 }
148158 if (!any_leaked)
149159 fprintf(gc_out, "none!\n");
160
161 fprintf(gc_out, "========================================\nleaked values:\n");
162 any_leaked = false;
163 for (i = 0; i < value_alloc.n; i++)
164 {
165
166 value = (struct xl_value *) value_alloc.elems[i];
167 err = xl_pointer_set_present(&present, &value_freed, value);
168 if (err != OK || present)
169 continue;
170 any_leaked = true;
171
172 fprintf(gc_out, "%016" PRIxPTR ":\n", (uintptr_t) value);
173 fprintf(gc_out, "\t%lu leaked refs\n", value->refcount);
174 fprintf(gc_out, "\t");
175 err = xl_value_print(&s, value);
176 if (err != OK)
177 fprintf(gc_out, "...couldn't print value");
178 fprintf(gc_out, "\n");
179 }
180 if (!any_leaked)
181 fprintf(gc_out, "none!\n");
150182 fprintf(gc_out, "========================================\n");
151183 #endif
184
152185 xl_vector_free(&graph_alloc);
153186 xl_vector_free(&graph_freed);
187 xl_vector_free(&value_alloc);
188 xl_vector_free(&value_freed);
154189
155190 xl_gc_free_all();
156191 free(gc_stats);
237272 no_ignore xl_error
238273 xl_value_new(struct xl_value **v)
239274 {
275 xl_error err;
276
240277 xl_assert(gc_stats != NULL);
241278
242279 *v = calloc(1, sizeof(struct xl_value));
247284
248285 #if XL_GC_DEBUG
249286 gc_stats->n_val_allocs++;
287
288 #if XL_GC_DEBUG_V
289 err = xl_pointer_set_add(NULL, &value_alloc, *v);
290 if (err != OK)
291 return err;
292 #endif
250293 #endif
251294
252295 return OK;
309352 return xl_raise(ERR_REFCOUNT_UNDERFLOW, "release");
310353 v->refcount--;
311354
312 #if XL_GC_DEBUG
313 gc_stats->n_val_frees++;
314 #endif
315
316355 err = OK;
317356
318357 if (v->refcount == 0)
321360 err = xl_release(v->left.any);
322361 if (err == OK && (v->tag & (TAG_RIGHT_NODE | TAG_RIGHT_GRAPH)))
323362 err = xl_release(v->right.any);
363
364 #if XL_GC_DEBUG
365 gc_stats->n_val_frees++;
366 #if XL_GC_DEBUG_V
367 err = xl_pointer_set_add(NULL, &value_freed, v);
368 if (err != OK)
369 return err;
370 #endif
371 #endif
372
324373 free(v);
325374 }
326375