Related articles |
---|
Bison, memory leaking md3den@mdstud.chalmers.se (Dennis Bj|rklund) (1997-05-25) |
Re: Bison, memory leaking cef@geodesic.com (Charles Fiterman) (1997-05-27) |
Re: Bison, memory leaking pfox@lehman.com (Paul David Fox) (1997-05-27) |
Re: Bison, memory leaking md3den@mdstud.chalmers.se (1997-06-02) |
Re: Bison, memory leaking sam.ravnborg@image.dk (1997-06-04) |
From: | sam.ravnborg@image.dk (Sam Ravnborg) |
Newsgroups: | comp.compilers |
Date: | 4 Jun 1997 22:50:19 -0400 |
Organization: | Image Scandinavia |
References: | 97-05-274 97-05-306 97-06-009 |
Keywords: | yacc, storage |
On 2 Jun 1997 10:29:37 -0400, md3den@mdstud.chalmers.se (Dennis
Bjorklund) wrote:
[snip - memory leak's when bison is in error-recovery mode]
>Before I changed bison I had a linked list with all things that were
>created and together with each object I had a pointer to the right
>destructor to call. Then we get lots of overhead that we don't need: a
>list of objects, problem with destructors, extra overhead when freeing
>memory (going through the linked list).
I have done it in this way too. What I did was to let all the
different class'es inherit from the same base class. The constructor
of the base class added the object to a list of allocated objects.
The destructor was made virtual and therefore the parent destructor
was called correct.
This solution have of course the drawbacks related to speed and size.
Furthermore I did not allow any object to be 'deleted' during the
parse.
Here's the code if any is interested:
// Linked list of all AST related classes. Used to free up space.
CAstBase *pAstBaseTop = NULL;
// DeleteAst is used to free up all memory used by the Ast,
// including any
// memory used for CType instances.
// The destructors in the various classes do the actual work.
void DeleteAst()
/*****************************************************************************
Summary: Free all memory used for the AST.
*****************************************************************************/
{
CAstBase *pAst = pAstBaseTop;
while ((pAst = pAstBaseTop) != NULL)
{
pAstBaseTop = pAst->pNext;
delete pAst;
}
}
// All clases that inherit from CAstBase are linked into a linked list
// when allocated. This allow us to free up ALL allocated items.
// Due to the fact that the parser stops as soon as an error is
// discovered
// and the AST may be inconsistent this base class is provided
// for cleanup.
class CAstBase
{
public:
CAstBase *pNext; // Next in list.
protected:
// Constructor link in new items in the front.
CAstBase()
{
extern CAstBase *pAstBaseTop;
pNext = pAstBaseTop; pAstBaseTop = this;
}
public:
virtual ~CAstBase() {} // Virtual to allow calls to derived class
};
And someone who used it:
// The upper part of the AST.
class CAst : CAstBase
{
/* Default constructor private to avoid illegal use */
CAst(void);
/* Type of CAst. */
NonTerminalList Nt;
...
};
Well, it worked for me. If I am going to improve it, I think there is
an area here to save time and space; one 'visible' pointer, and one
'invisible' due to the virtual function, and thats for each tiny
object!
/sam
--
Return to the
comp.compilers page.
Search the
comp.compilers archives again.