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

Cristian Târşoagă cristian.tarsoaga at gmail.com
Thu May 20 05:48:37 PDT 2010


Hi Mark,

thanks a lot, I think that is what I was looking for!
once I'll be able to install a custom deleter, my problems are solved!
allocation was not a problem even without using 'placement' new, but
deletion was a problem indeed (only when the rule was failing, leaks could
occur)

Honestly, I never thought to put something like this:
ctx->pMyGrammarParser_GSTop->free = &free_MyStruct;
in the @init action, I thought that maybe there is a general way to install
the deleter, using a macro...I don't know...

But you're right, this WILL delete my pointers properly, THANKS!!   :-)

    Chris





2010/5/20 Mark Wright <markwright at internode.on.net>

> 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