[antlr-interest] C target - initialization of return/scope structures

Mark Wright markwright at internode.on.net
Thu May 20 05:13:56 PDT 2010


On Thu, May 20, 2010 at 10:04:09AM +0300, Cristian Târşoagă wrote:
> Hi Jim, that is not my problem, let me show you an example
> 
> I want to have a scoped value which is a structure, and my structure holds
> some std::strings
> 
> struct MyStruct
> {
>   std::string s1;
>   std::string s2;
> };
> 
> //this is part of my grammar
> myrule
> scope {MyStruct s;} //scoped VALUE
> @init{}
> @after{}
> : rulegoeshere....;
> 
> As you can see, there is no pointer here, the scoped variable is a 'value'.
> The code generated by antlr creates a scoped wrapper structure that holds
> MyStruct, something like:
> 
> ctx->pMyParser_myruleTop = pMyParser_myrulePush(ctx); // this will create a
> wrapper for the scoped value by calling ANTLR3_MALLOC
> 
> the wrapper looks like this:
> 
> typedef struct  MyParser_myrule_SCOPE_struct
> {
>     void    (ANTLR3_CDECL *free)    (struct MyParser_myrule_SCOPE_struct *
> frame);
>     MyStruct s;
> }
> 
> As you can see my struct is inside this structure. The problem is that to
> create the wrapper (see pMyParser_myrulePush above)
> antlr calls ANTLR3_MALLOC (which does malloc of course).
> 
> THIS MEANS I'M GONNA GET A CRASH!
> 
> Why? because std::string is a c++ class, which HAS to be created/destroyed
> using new/delete, not malloc/free.

Hi Cristian,

As Jim advised, you need to initialise it in @init().  As the memory has
already been allocated, the correct way to initialise it is to call the
constructor with placement operator new.

And it is necessary to register your own free method to call the destructor.

grammar MyGrammar;

options {
        language = C;
}

scope GS {
  MyStruct s;
}

@parser::includes {
#include <new>
#include "MyStruct.h"
}

myrule
scope GS;
@init{
  new(&($GS::s))MyStruct;
  ctx->pMyGrammarParser_GSTop->free = &free_MyStruct;
}
        : 'foo'
        | 'bar'
        ;

mystruct.h:
#include <string>
#include <antlr3.h>

struct MyStruct
{
  std::string s1;
  std::string s2;
};

extern "C" {
  void ANTLR3_CDECL free_MyStruct(struct MyGrammarParser_GS_SCOPE_struct *scope);
}

mystruct.cpp:
extern "C" {
void ANTLR3_CDECL free_MyStruct(struct MyGrammarParser_GS_SCOPE_struct *scope)
{
  // Call the destructor
  (&(scope->s))->MyStruct::~MyStruct();
}
}

Regards, Mark
 
> That means, I cannot use a scoped VALUE, I have to use a scoped POINTER
> instead, as suggested here:
> 
> http://www.mail-archive.com/il-antlr-interest@googlegroups.com/msg02614.html
> 
> 
> 
> Suggested Solution 1: local new/delete allocation/deallocation
> ------------------------------
> -----------------------------------------------------------
> So my rule will now look like this:
> 
> myrule
> scope {MyStruct* s;} //scoped POINTER
> @init{ $myrule::s = new MyStruct();} //explicit allocation using new
> @after{ delete $myrule::s; } //explicit deallocation using delete
> : rulegoeshere....;
> 
> Looks good? Well, I think not!
> Because when the rule fails, the @after action is NOT called, and I'm gonna
> get a nice memory leak.
> 
> Solution 1': the scoped wrapper has a member called free that can hold a
> 'deleter', but I couldn't find a way to set that.
> 
> 
> Suggested Solution2: override antlr macros ANTLR3_MALLOC and ANTLR3_FREE
> ------------------------------------------------------------------------------------------------------------------------
> 
> Nice try, but ANTLR3_MALLOC is currently defined like this:
> #define    ANTLR3_MALLOC(request)                    malloc
> ((size_t)(request))
> 
> As you can see, the 'request' argument is a SIZE, not a type, which means
> that if I want to override it to make it use 'new' instead of malloc, I
> cannot use it.
> >From the given size I cannot deduce the type (this could work the other way
> around if you change the define, to pass it the type you could get the size,
> and it could be possible to override the default way of antlr's
> allocations/deallocations)
> 
> 
> 
> That is my problem and those are the options I have. Maybe with some
> adjustment some of them will work, but right now, I'm not happy with any of
> them: first one leaks, second one is not usable.
> 
> Maybe you have some hints for me :-)
> 
> Thanks a lot for your answer
> 
>    Chris
> 
> List: http://www.antlr.org/mailman/listinfo/antlr-interest
> Unsubscribe: http://www.antlr.org/mailman/options/antlr-interest/your-email-address
> 


More information about the antlr-interest mailing list