On Sat, Sep 27, 2014 at 12:23:37AM +0200, Hans Aberg wrote: > > > On 26 Sep 2014, at 21:58, Bob Rossi <b...@brasko.net> wrote: > > > > On Fri, Sep 26, 2014 at 03:37:18PM +0200, Hans Aberg wrote: > > >>> The %destructor for result and result_list does not call free, but > >>> instead calls gdbmi_result_free. gdbmi_result_free free's the result > >>> (including the variable member of the result), and the result's next > >>> pointer, and so on. > >>> > >>> Is it correct for me to call gdbmi_result_free($$) instead of free($$)? > >> > >> The %destructor is for making C style cleanup during an error recovery: > >> the Bison generated parser will then skip forward, bypassing any normal > >> deallocations in the actions. So first write the parser in normal C style, > >> with deallocators in each instance matching the allocator used in the > >> actions. Then add %destructor if needed for the error recovery. > > > > Unfortunately, this confused me more than clarified things. > > > > What are the 'normal deallocations in the actions?' I only ever put > > allocations in the actions, never deallocations. > > Then it will leak for everything that you do no deallocate during normal, > error-free parsing. > > > In the second sentence you mentioned I should write deallocators in each > > instance matching the allocator used in the actions. THEN add > > %destructor if needed for error recovery. > > > > Where do I put deallocators in the bison generator parser, besides > > %destructor? > > I am normally using C++, which is doing the cleanup, but let’s try C > (pseudocode): > > list: > "[“ sequence[x] "]" { $$ = $x; } > ; > > sequence: > item[x] { $$ = make_list1($x); free($x); } > | sequence[s] "," item[x] { $$ = make_list($s, $x); free($s); free($x); } > ;
OK. Thanks for explaining. I took a different strategy here. Maybe my strategy is wrong. You can see a slightly out of date version of my grammar here, https://github.com/brasko/gdbwire/blob/master/src/lib/gdbmi/gdbmi_grammar.y Please consider the following type, struct gdbmi_result { enum gdbmi_result_kind kind; char *variable; union { char *cstring; struct gdbmi_result *result; } variant; struct gdbmi_result *next; }; Please consider the following result_list rules, result_list: { $$ = NULL; }; result_list: result_list COMMA result { $$ = append_gdbmi_result ($1, $3); }; result: opt_variable CSTRING { $$ = gdbmi_result_alloc(); $$->variable = $1; $$->kind = GDBMI_CSTRING; $$->variant.cstring = strdup(gdbmi_text); }; result: opt_variable tuple { $$ = gdbmi_result_alloc(); $$->variable = $1; $$->kind = GDBMI_TUPLE; $$->variant.result = $2; }; result: opt_variable list { $$ = gdbmi_result_alloc(); $$->variable = $1; $$->kind = GDBMI_LIST; $$->variant.result = $2; }; My approach is to build up $$. I never deallocate in the actions, and valgrind claims I have no memory leaks in the unit tests. In the end, on a successful parse, I end up with a 'struct gdbmi_result *' which has the next pointer set, etc. Hopefully the above is an OK strategy. The problem I'm facing is related to error handling for sure. If I add this, (and I use malloc under the hood for all allocations) %destructor { free($$); } result result_list; I still have memory leaks (valgrind assures me). I'm not a bison expert, and so it's not exactly obvious to me which items it chooses to call the destructor on. If I change the free routine to %destructor { gdbmi_result_free($$); } result result_list; then the memory leaks go away (according to valgrind). gdbmi_result_free free's each member in 'struct gdbmi_result' and also free's the next field. Since I don't understand what exactly Bison calls the destructor on, I'm wondering, 1) If I free the entire struct gdbmi_result with gdbmi_result_free($$) and I also have a destructor for $1 in the above examples, %destructor { free($$); } variable Is it possible I'll have a double free? 2) Because I'm using gdbmi_result_free($$) which also free's the next pointer of a list, is it possible Bison will also call the destructor on each member of the list item, causing a double free? I know I'm not doing a great job here asking this question. Sorry. If this is to unclear, I'll spend some time formulating a much more precise question, which may perhaps help me answer my own question. Thanks! Bob Rossi _______________________________________________ help-bison@gnu.org https://lists.gnu.org/mailman/listinfo/help-bison