Why yacc have memory leak at exit?
bison, c, lex, memory-leaks, yacc
Solution
==10006== LEAK SUMMARY:
==10006== definitely lost: 0 bytes in 0 blocks
==10006== indirectly lost: 0 bytes in 0 blocks
==10006== possibly lost: 0 bytes in 0 blocks
==10006== still reachable: 16,458 bytes in 3 blocks
==10006== suppressed: 0 bytes in 0 blocks
Not freeing still reachable memory is quite normal for most programs. Since there is still a pointer to it at exit, it's not really a leak.
Problem
when I execute my lex/yacc program with valgrind, it find memory leak. But I would know if it's possible to delete this memory leak. The output of valgrind is: ``` ==10006== ==10006== HEAP SUMMARY: ==10006== in use at exit: 16,458 bytes in 3 blocks ==10006== total heap usage: 13 allocs, 10 frees, 16,684 bytes allocated ==10006== ==10006== 8 bytes in 1 blocks are still reachable in loss record 1 of 3 ==10006== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10006== by 0x4028FA: yyalloc (lex.yy.c:1852) ==10006== by 0x402411: yyensure_buffer_stack (lex.yy.c:1552) ==10006== by 0x400DA9: yylex (lex.yy.c:686) ==10006== by 0x40312D: yyparse (parser.tab.c:1183) ==10006== by 0x40462F: parse (Parser.c:10) ==10006== by 0x4045EB: main (main.c:21) ==10006== ==10006== 64 bytes in 1 blocks are still reachable in loss record 2 of 3 ==10006== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10006== by 0x4028FA: yyalloc (lex.yy.c:1852) ==10006== by 0x401FA5: yy_create_buffer (lex.yy.c:1387) ==10006== by 0x400DD3: yylex (lex.yy.c:688) ==10006== by 0x40312D: yyparse (parser.tab.c:1183) ==10006== by 0x40462F: parse (Parser.c:10) ==10006== by 0x4045EB: main (main.c:21) ==10006== ==10006== 16,386 bytes in 1 blocks are still reachable in loss record 3 of 3 ==10006== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==10006== by 0x4028FA: yyalloc (lex.yy.c:1852) ==10006== by 0x401FDC: yy_create_buffer (lex.yy.c:1396) ==10006== by 0x400DD3: yylex (lex.yy.c:688) ==10006== by 0x40312D: yyparse (parser.tab.c:1183) ==10006== by 0x40462F: parse (Parser.c:10) ==10006== by 0x4045EB: main (main.c:21) ==10006== ==10006== LEAK SUMMARY: ==10006== definitely lost: 0 bytes in 0 blocks ==10006== indirectly lost: 0 bytes in 0 blocks ==10006== possibly lost: 0 bytes in 0 blocks ==10006== still reachable: 16,458 bytes in 3 blocks ==10006== suppressed: 0 bytes in 0 blocks ==10006== ==10006== For counts of detected and suppressed errors, rerun with: -v ==10006== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ``` And my lex: ``` Chiffre [0-9] Lettre [a-zA-Z] Alphanum ({Chiffre}{Lettre})+ %{ #include <string.h> #include <stdio.h> #include <stdlib.h> #include "parser.tab.h" %} %% -[a-zA-Z]+ { yylval. string = strdup(yytext); return OPTION; } [a-zA-Z0-9_\-./]+ { yylval.string = strdup(yytext); return WORD; } "||" { return OR; } "|" { return PIPE; } "&&" { return AND; } "&" { return AMPERSAND; } ";" { return SEMICOLON; } "2>" { return ERR_GREAT; } ">&" { return GREAT_AMP; } "2>>" { return ERR_GREAT_GREAT; } ">>&" { return GREAT_GREAT_AMP; } ">>" { return GREAT_GREAT; } ">" { return GREAT; } "<" { return LESS; } [ \t]+ { } "\n" { return 0; } %% ``` And my yacc file: ``` %{ #include <stdio.h> #include "executor/CmdArg.h" #include "executor/Command.h" #include "print.h" int yyerror(const char *msg) { return fprintf(stderr, "YACC: %s\n", msg); } %} %union { int number; char *string; }; %token<string> WORD %token<string> OPTION %destructor { free($$); } <string> %token<void> SEMICOLON %token OR AND PIPE AMPERSAND GREAT GREAT_GREAT LESS ERR_GREAT ERR_GREAT_GREAT GREAT_AMP GREAT_GREAT_AMP %error-verbose %% pipeline: cmd_args background SEMICOLON pipeline{ end_cmd(SEQUENCING_SEQUENCING); } | cmd_args background PIPE pipeline{ end_cmd(SEQUENCING_PIPE); } | cmd_args background OR pipeline{ end_cmd(SEQUENCING_OR); } | cmd_args background AND pipeline{ end_cmd(SEQUENCING_AND); } | cmd_args background{ end_cmd(SEQUENCING_NOTHING); } |; cmd_args: WORD list_args params io_list{ printdebug("YACC COMMMAND : %s\n", $1); add_arg($1); }; list_args: OPTION list_args{ printdebug ("yacc list arg plusieurs: %s\n", $1); add_arg($1); }|OPTION{ printdebug ("yacc list arg seul : %s\n", $1); add_arg($1); }|; params: WORD params{ printdebug ("yacc param plusieurs : %s\n", $1); add_arg($1); } |WORD { printdebug ("yacc param seul: %s\n", $1); add_arg($1); }|; background: AMPERSAND{ set_background(); } |; io_list: GREAT WORD{ set_io(GREAT,$2); }|GREAT_GREAT WORD{ set_io(GREAT_GREAT,$2); } LESS WORD{ set_io(LESS,$2); }| ERR_GREAT WORD{ set_io(ERR_GREAT,$2); }| ERR_GREAT_GREAT WORD{ set_io(ERR_GREAT_GREAT,$2); }| GREAT_AMP WORD{ set_io(GREAT_AMP,$2); }| GREAT_GREAT_AMP WORD{ set_io(GREAT_GREAT_AMP,$2); }|; %% struct CmdArg *temp; void set_io(enum yytokentype tokentype, char* file){ } void set_background() { temp->_background = 1; } void add_arg(char* s){ if (!temp)temp = new_cmdArg(); cmdarg_add_argument(temp,s); free(s); } void end_cmd(Sequencing seq){ temp->_seq=seq; command_add_cmdArg(temp, seq); free_cmdArg(temp); temp = NULL; } ``` Thank you for your help.