yylex_destroy() is well hidden!
If you notice, in ADHOC’s makefile, there is a recipe called ‘grind’ that I use as a quick spot-check for memory leaks and other issues during builds. For the longest time, ‘grind’ kept showing a couple un-freed memory blocks after
yyparse had finished parsing my input files, and I couldn’t figure out where the blocks were being allocated. Valgrind kept pointing to YACC/Bison‘s
lex.yy.c code file, so I figured it must be a YACC issue, and I went Googling.
I found a number of issues related to
yytext being copied improperly or the
YYSTYPE union not being destroyed on encountering a syntax error, but I checked on a minimal set of ADHOC’s grammar rules and with no syntax errors, and got the same un-freed blocks. Finally, I found a post (that I cannot seem to find again), which mentioned that in YACC’s underlying DFA implementation, the final accepting state of the parse is never popped off the DFA’s stack, and that this was an inevitable (but “harmless”!) idiosyncrasy. Of course would not do. So I spent the next 20 minutes or so reading through
lex.yy.c, and eventually found that there is a function called
yylex_destroy, which, among other things, frees and remaining DFA states and the stack itself!
// Parse the input file/stream int parseResult; parseResult = yyparse(); // Clean up parse lookahead yylex_destroy(); // <-- WOW This was hard to find!
Googling 'yylex_destroy' gets about 18k results, and none that I have seen, mention anything about clearing the DFA stack. It seems like this function should get called internally by YACC itself, and shouldn't be for the programmer to worry about, but I do not see that to be the case. Anyway, after sticking it into ADHOC's
main function (just under the call to
yyparse), the memory leak cleared up right away. Yay documentation!