0

I've read online that you can free memory in bison like this:

statement:
         INTEGER
         {
             //Do Something
             free($1);
         }

Where the integer token is returned by flex like this:

[0-9]+        {  yylval.integer_value = atoi(yytext); return INTEGER; }

(integer_value is defined as an int)

When I try to free($1), I get:

passing argument 1 of ‘free’ makes pointer from integer without a cast

Which makes sense, but I have seen online examples where you can free memory like this. How can I solve this?

user207421
  • 305,947
  • 44
  • 307
  • 483
user7637341
  • 421
  • 1
  • 6
  • 15
  • 1
    Why do you need to free anything? It's an `int` not a pointer to some memory – Chris Turner Oct 13 '17 at 12:21
  • @ChrisTurner Yeah I suppose that's more like the question. What do I need to free then? I run valgrind and I have memory unfreed. I assume it must be bison allocating something but not freeing it. – user7637341 Oct 13 '17 at 12:23
  • 1
    In what way is this a C question? – David Hoelzer Oct 13 '17 at 12:24
  • 1
    @DavidHoelzer bison generates C code – Chris Turner Oct 13 '17 at 12:40
  • 2
    @user7637341 valgrind should be telling you where in the code the memory is being allocated, so that should give you an idea what needs to be freed and when – Chris Turner Oct 13 '17 at 12:42
  • 1
    "I read it somewhere on the internet" is not a very precise citation, and it is, in general, hard to answer questions which start with a statement like that because it is not possible to see what is being reacted to. However, since I've frequently offered bison advice which includes the use of `free($n)` in actions, I hasten to add that I am usually referring to the case where the semantic value is a previously `strdup`ed token string, not an integer. – rici Oct 13 '17 at 15:21
  • @rici Yep, i've since discovered its just the flex/bison background stuff, nothing to do with this variable. – user7637341 Oct 13 '17 at 15:45
  • 1
    @user7637341: bison doesn't leak memory unless you do something like `exit(0)` in an error action. For flex, see https://stackoverflow.com/a/43671616/1566221 (which is a near duplicate) – rici Oct 13 '17 at 16:59
  • @DavidHoelzer `free()` is part of the C library. – user207421 Oct 13 '17 at 23:26
  • I am completely aware that Bison generates C code and that free is part of the C library... but is this a question on writing Bison code or on writing C code? – David Hoelzer Oct 13 '17 at 23:28
  • 'I read it somewhere on the Internet' is usually a really good reason *not* to do it, unless you read it in a reference manual, or somewhere so authoritative that you remember where it is (such as a heavily upvoted and non-criticized answer here). 90% of everything is crap, and the Internet is no exception. – user207421 Oct 13 '17 at 23:28
  • @DavidHoelzer It is a question about writing C code in a Bison production. That's how you use it. – user207421 Oct 13 '17 at 23:29

2 Answers2

2

Most commonly you would need to free memory in an action if it was allocated in an earlier action or the lexer. For example you might have a flex rule:

[a-zA-Z_][a-zA-Z_0-9]*    { yylval.id = strdup(yytext); return IDENT; }

this rule allocates memory (the strdup call), so you would like to ensure that the memory eventually gets freed and does not leak. So you might have

statement: IDENT {
            // do something
            free($1);
        }

Note that you only want to free the memory here if you don't store the pointer in some other data structure that you're going to use (and free) later. It is also tricky to free memory in the presence of error recovery. Bison gives you a special %destructor directive that can be used to tell the parser how to clean up the parse stack when recovering from an error:

%destructor { free($1); } <id>

This will free the memory allocated/owned by any symbol with a %type or %token of <id> when that symbol is discarded as part of error recovery, or with a YYABORT or YYACCEPT directive.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
0

If $1 was the result of a malloc() or calloc() or strdup(), typically as the target value $$ of another production, or a side effect of a lexer action in yylval, you must free it some time: otherwise you must not.

user207421
  • 305,947
  • 44
  • 307
  • 483