From 9e7e804d1a6b91f98445a172c62cdc66e009130d Mon Sep 17 00:00:00 2001 From: werner Date: Fri, 21 Aug 2009 08:34:17 +0000 Subject: [PATCH] - delete.c: added more destructor functions - deallocate all our data structures on exit (to help find memory leaks, bad pointers, and general logic errors) - fixed memory leak when allocating pad names in instantiation - added "magic" environment variable FPED_NO_GUI to run fped without initializing Gtk+ - added valgrind wrapper "leakcheck" - delete.c: destroy() now requires a deletion to exist - vacate_op: free string expressions - destroy_obj: free measurement labels - delete_references: use do_delete_obj so the we don't bump the group number - delete_frame: delete references after deleting the frame itself, so they end up on the stack above the frame and get destroyed first - do_delete_vec: like above, even though it doesn't matter here git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5506 99fdad57-331a-0410-800a-d7fa5415bdb3 --- delete.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++------ delete.h | 3 +- expr.c | 7 +++- fped.c | 27 +++++++------ inst.c | 13 +++++++ inst.h | 2 +- leakcheck | 13 +++++++ obj.c | 14 +++++++ obj.h | 1 + util.c | 16 +++++++- util.h | 1 + 11 files changed, 182 insertions(+), 27 deletions(-) create mode 100755 leakcheck diff --git a/delete.c b/delete.c index 8f0c052..0947b87 100644 --- a/delete.c +++ b/delete.c @@ -146,9 +146,6 @@ static void do_delete_vec(struct vec *vec) struct vec *walk, *prev; struct deletion *del; - delete_vecs_by_ref(vec->frame->vecs, vec); - delete_objs_by_ref(&vec->frame->objs, vec); - prev = NULL; for (walk = vec->frame->vecs; walk != vec; walk = walk->next) prev = walk; @@ -159,6 +156,9 @@ static void do_delete_vec(struct vec *vec) del = new_deletion(dt_vec); del->u.vec.ref = vec; del->u.vec.prev = prev; + + delete_vecs_by_ref(vec->frame->vecs, vec); + delete_objs_by_ref(&vec->frame->objs, vec); } @@ -204,6 +204,8 @@ static void destroy_obj(struct obj *obj) free_expr(obj->u.arc.width); break; case ot_meas: + if (obj->u.meas.label) + free(obj->u.meas.label); if (obj->u.meas.offset) free_expr(obj->u.meas.offset); break; @@ -257,6 +259,20 @@ static void undelete_obj(struct obj *obj, struct obj *prev) /* ----- rows -------------------------------------------------------------- */ +static void destroy_row(struct row *row) +{ + struct value *next_value; + + while (row->values) { + next_value = row->values->next; + free_expr(row->values->expr); + free(row->values); + row->values = next_value; + } + free(row); +} + + void delete_row(struct row *row) { struct deletion *del; @@ -355,6 +371,23 @@ static void undelete_column(const struct column *col) /* ----- tables ------------------------------------------------------------ */ +static void destroy_table(struct table *table) +{ + struct var *next_var; + + while (table->vars) { + next_var = table->vars->next; + free(table->vars); + table->vars = next_var; + } + while (table->rows) { + delete_row(table->rows); + destroy(); + } + free(table); +} + + void delete_table(struct table *table) { struct frame *frame = table->vars->frame; @@ -392,6 +425,14 @@ static void undelete_table(struct table *table, struct table *prev) /* ----- loops ------------------------------------------------------------- */ +static void destroy_loop(struct loop *loop) +{ + free_expr(loop->from.expr); + free_expr(loop->to.expr); + free(loop); +} + + void delete_loop(struct loop *loop) { struct frame *frame = loop->var.frame; @@ -429,6 +470,28 @@ static void undelete_loop(struct loop *loop, struct loop *prev) /* ----- frames ------------------------------------------------------------ */ +static void destroy_frame(struct frame *frame) +{ + while (frame->tables) { + delete_table(frame->tables); + destroy(); + } + while (frame->loops) { + delete_loop(frame->loops); + destroy(); + } + while (frame->vecs) { + delete_vec(frame->vecs); + destroy(); + } + while (frame->objs) { + delete_obj(frame->objs); + destroy(); + } + free(frame); +} + + static void delete_references(const struct frame *ref) { struct frame *frame; @@ -438,7 +501,7 @@ static void delete_references(const struct frame *ref) for (obj = frame->objs; obj; obj = obj->next) if (obj->type == ot_frame) if (obj->u.frame.ref == ref) - delete_obj(obj); + do_delete_obj(obj); } @@ -447,7 +510,6 @@ void delete_frame(struct frame *frame) struct deletion *del; groups++; - delete_references(frame); del = new_deletion(dt_frame); del->u.frame.ref = frame; @@ -459,6 +521,8 @@ void delete_frame(struct frame *frame) frame->prev->next = frame->next; else frames = frame->next; + + delete_references(frame); } @@ -478,12 +542,10 @@ static void undelete_frame(struct frame *frame, struct frame *prev) /* ----- destroy/undelete interface ---------------------------------------- */ -int destroy(void) +static void destroy_one(void) { struct deletion *del; - if (!deletions) - return 0; del = deletions; switch (del->type) { case dt_vec: @@ -493,15 +555,36 @@ int destroy(void) destroy_obj(del->u.obj.ref); break; case dt_frame: - abort(); - /* @@@ later */ + destroy_frame(del->u.frame.ref); + break; + case dt_loop: + destroy_loop(del->u.loop.ref); + break; + case dt_table: + destroy_table(del->u.table.ref); + break; + case dt_row: + destroy_row(del->u.row.ref); + break; + case dt_column: + abort(); /* @@@ later */ break; default: abort(); } deletions = del->next; free(del); - return 1; +} + + +void destroy(void) +{ + int group; + + assert(deletions); + group = deletions->group; + while (deletions && deletions->group == group) + destroy_one(); } @@ -554,3 +637,10 @@ int undelete(void) undelete_one(); return 1; } + + +void purge(void) +{ + while (deletions) + destroy(); +} diff --git a/delete.h b/delete.h index 5257990..0815880 100644 --- a/delete.h +++ b/delete.h @@ -25,7 +25,8 @@ void delete_column(struct table *table, int n); void delete_table(struct table *table); void delete_loop(struct loop *loop); void delete_frame(struct frame *frame); -int destroy(void); +void destroy(void); int undelete(void); +void purge(void); #endif /* !DELETE_H */ diff --git a/expr.c b/expr.c index f9a6333..bd2463c 100644 --- a/expr.c +++ b/expr.c @@ -459,9 +459,12 @@ struct expr *parse_expr(const char *s) static void vacate_op(struct expr *expr) { - if (expr->op == op_num || expr->op == op_string || - expr->op == op_var) + if (expr->op == op_num || expr->op == op_var) return; + if (expr->op == op_string) { + free(expr->u.str); + return; + } if (expr->op == op_minus) { free_expr(expr->u.op.a); return; diff --git a/fped.c b/fped.c index 7c277bc..48c27f9 100644 --- a/fped.c +++ b/fped.c @@ -22,6 +22,7 @@ #include "inst.h" #include "file.h" #include "gui.h" +#include "delete.h" #include "fpd.h" @@ -55,10 +56,13 @@ int main(int argc, char **argv) int error; int batch_write_kicad = 0, batch_write_ps = 0; int c; + int have_gui = !getenv("FPED_NO_GUI"); - error = gui_init(&argc, &argv); - if (error) - return error; + if (have_gui) { + error = gui_init(&argc, &argv); + if (error) + return error; + } while ((c = getopt(argc, argv, "kp")) != EOF) switch (c) { @@ -102,15 +106,16 @@ int main(int argc, char **argv) write_kicad(); if (batch_write_ps) write_ps(); - if (batch_write_kicad || batch_write_ps) - exit(0); - -// inst_debug(); - error = gui_main(); - if (error) - return error; + if (have_gui && !batch_write_kicad && !batch_write_ps) { + error = gui_main(); + if (error) + return error; + } -// dump(stdout); + purge(); + inst_revert(); + obj_cleanup(); + unique_cleanup(); return 0; } diff --git a/inst.c b/inst.c index 5c6771a..38e94e6 100644 --- a/inst.c +++ b/inst.c @@ -956,6 +956,18 @@ struct bbox inst_get_bbox(void) } +static void cleanup_inst(enum inst_prio prio, const struct inst *inst) +{ + switch (prio) { + case ip_pad: + free(inst->u.pad.name); + break; + default: + break; + } +} + + static void free_pkgs(struct pkg *pkg) { enum inst_prio prio; @@ -967,6 +979,7 @@ static void free_pkgs(struct pkg *pkg) FOR_INST_PRIOS_UP(prio) for (inst = pkg->insts[prio]; inst; inst = next) { next = inst->next; + cleanup_inst(prio, inst); free(inst); } reset_samples(pkg->samples, pkg->n_samples); diff --git a/inst.h b/inst.h index 4dd2eb7..8b1f9ab 100644 --- a/inst.h +++ b/inst.h @@ -88,7 +88,7 @@ struct inst { unit_type width; } rect; struct { - const char *name; + char *name; struct coord other; } pad; struct { diff --git a/leakcheck b/leakcheck new file mode 100755 index 0000000..8c6920c --- /dev/null +++ b/leakcheck @@ -0,0 +1,13 @@ +#!/bin/sh +#valgrind --leak-check=full --show-reachable=yes --suppressions=leak.supp \ +# ./fped "$@" + +# +# Seems that we can't suppress warnings from gtk_init, so we use FPED_NO_GUI +# to avoid bringing up Gtk+ at all. +# +FPED_NO_GUI=y valgrind --leak-check=full --show-reachable=yes \ + ./fped "$@" + +#valgrind --leak-check=full --show-reachable=no \ +# ./fped "$@" diff --git a/obj.c b/obj.c index be04432..3b09ff7 100644 --- a/obj.c +++ b/obj.c @@ -20,6 +20,7 @@ #include "expr.h" #include "meas.h" #include "inst.h" +#include "delete.h" #include "obj.h" @@ -288,3 +289,16 @@ int instantiate(void) inst_revert(); return ok; } + + +/* ----- deallocation ------------------------------------------------------ */ + + +void obj_cleanup(void) +{ + free(pkg_name); + while (frames) { + delete_frame(frames); + destroy(); + } +} diff --git a/obj.h b/obj.h index 6b05d61..4bb4804 100644 --- a/obj.h +++ b/obj.h @@ -191,5 +191,6 @@ extern void *instantiation_error; int instantiate(void); +void obj_cleanup(void); #endif /* !OBJ_H */ diff --git a/util.c b/util.c index 18204f5..cbc506c 100644 --- a/util.c +++ b/util.c @@ -79,7 +79,7 @@ int is_id(const char *s) static struct unique { - const char *s; + char *s; struct unique *next; } *uniques = NULL; @@ -98,3 +98,17 @@ const char *unique(const char *s) (*walk)->next = NULL; return (*walk)->s; } + + +void unique_cleanup(void) +{ + struct unique *next; + + while (uniques) { + next = uniques->next; + free(uniques->s); + free(uniques); + uniques = next; + } +} + diff --git a/util.h b/util.h index feb1e59..426f0ae 100644 --- a/util.h +++ b/util.h @@ -60,5 +60,6 @@ int is_id_char(char c, int first); int is_id(const char *s); const char *unique(const char *s); +void unique_cleanup(void); #endif /* !UTIL_H */