Skip to content

Commit

Permalink
Fixed a number of memory leaks in the template engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimitri van Heesch committed Sep 13, 2015
1 parent 76a9892 commit d14bcd1
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 6 deletions.
23 changes: 23 additions & 0 deletions src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3845,6 +3845,7 @@ TemplateVariant createLinkedText(Definition *def,const QCString &relPath,const Q
if (tg)
{
linkifyText(*tg,def->getOuterScope(),def->getBodyDef(),def,text);
delete tg;
return TemplateVariant(s.data(),TRUE);
}
else
Expand Down Expand Up @@ -10201,6 +10202,28 @@ void generateOutputViaTemplate()
}
}

// clear all cached data in Definition objects.
QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap);
DefinitionIntf *intf;
for (;(intf=di.current());++di)
{
if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
{
DefinitionListIterator dli(*(DefinitionList*)intf);
Definition *d;
// for each symbol
for (dli.toFirst();(d=dli.current());++dli)
{
d->setCookie(0);
}
}
else // single symbol
{
Definition *d = (Definition *)intf;
d->setCookie(0);
}
}

e.destroyContext(ctx);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class RefCountedContext
m_className=className;
m_insideRelease = FALSE;
}
~RefCountedContext()
virtual ~RefCountedContext()
{
if (!m_insideRelease) abort();
}
Expand Down
1 change: 1 addition & 0 deletions src/definition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ Definition::~Definition()
m_impl=0;
}
delete m_cookie;
m_cookie=0;
}

void Definition::setName(const char *name)
Expand Down
7 changes: 5 additions & 2 deletions src/definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ class DefinitionIntf
class Definition : public DefinitionIntf
{
public:
struct Cookie {};
struct Cookie
{
virtual ~Cookie() {}
};

/*! Create a new definition */
Definition(
Expand Down Expand Up @@ -345,7 +348,7 @@ class Definition : public DefinitionIntf
void addSectionsToIndex();
void writeToc(OutputList &ol);

void setCookie(Cookie *cookie) { m_cookie = cookie; }
void setCookie(Cookie *cookie) { delete m_cookie; m_cookie = cookie; }
Cookie *cookie() const { return m_cookie; }

protected:
Expand Down
1 change: 1 addition & 0 deletions src/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,7 @@ class LayoutParser : public QXmlDefaultHandler

private:
LayoutParser() : m_sHandler(163), m_eHandler(17), m_invalidEntry(FALSE) { }
~LayoutParser() { delete m_rootNav; }

QDict<StartElementHandler> m_sHandler;
QDict<EndElementHandler> m_eHandler;
Expand Down
42 changes: 39 additions & 3 deletions src/template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,10 @@ class ExprAstFunctionVariable : public ExprAst
{ TRACE(("ExprAstFunctionVariable()\n"));
m_args.setAutoDelete(TRUE);
}
~ExprAstFunctionVariable()
{
delete m_var;
}
virtual TemplateVariant resolve(TemplateContext *c)
{
QValueList<TemplateVariant> args;
Expand Down Expand Up @@ -2260,6 +2264,7 @@ class TemplateImpl : public TemplateNode, public Template
public:
TemplateImpl(TemplateEngine *e,const QCString &name,const QCString &data,
const QCString &extension);
~TemplateImpl();
void render(FTextStream &ts, TemplateContext *c);

TemplateEngine *engine() const { return m_engine; }
Expand All @@ -2274,6 +2279,22 @@ class TemplateImpl : public TemplateNode, public Template

//----------------------------------------------------------

/** @brief Weak reference wrapper for TemplateStructIntf that provides access to the
* wrapped struct without holding a reference.
*/
class TemplateStructWeakRef : public TemplateStructIntf
{
public:
TemplateStructWeakRef(TemplateStructIntf *ref) : m_ref(ref), m_refCount(0) {}
virtual TemplateVariant get(const char *name) const { return m_ref->get(name); }
virtual int addRef() { return ++m_refCount; }
virtual int release() { int count=--m_refCount; if (count<=0) { delete this; } return count; }
private:
TemplateStructIntf *m_ref;
int m_refCount;
};

//----------------------------------------------------------

TemplateContextImpl::TemplateContextImpl(const TemplateEngine *e)
: m_engine(e), m_templateName("<unknown>"), m_line(1), m_activeEscapeIntf(0),
Expand Down Expand Up @@ -2418,7 +2439,7 @@ void TemplateContextImpl::warn(const char *fileName,int line,const char *fmt,...

void TemplateContextImpl::openSubIndex(const QCString &indexName)
{
//printf("TemplateContextImpl::openSubIndex(%s)\n",indexName.data());
printf("TemplateContextImpl::openSubIndex(%s)\n",indexName.data());
QStack<TemplateVariant> *stack = m_indexStacks.find(indexName);
if (!stack || stack->isEmpty() || stack->top()->type()==TemplateVariant::List) // error: no stack yet or no entry
{
Expand All @@ -2439,7 +2460,7 @@ void TemplateContextImpl::openSubIndex(const QCString &indexName)

void TemplateContextImpl::closeSubIndex(const QCString &indexName)
{
//printf("TemplateContextImpl::closeSubIndex(%s)\n",indexName.data());
printf("TemplateContextImpl::closeSubIndex(%s)\n",indexName.data());
QStack<TemplateVariant> *stack = m_indexStacks.find(indexName);
if (!stack || stack->count()<3)
{
Expand All @@ -2462,6 +2483,7 @@ void TemplateContextImpl::closeSubIndex(const QCString &indexName)
}
}
}
//fprintf(stderr,"TemplateContextImpl::closeSubIndex(%s) end g_count=%d\n\n",indexName.data(),g_count);
}

static void getPathListFunc(TemplateStructIntf *entry,TemplateList *list)
Expand Down Expand Up @@ -2520,7 +2542,9 @@ void TemplateContextImpl::addIndexEntry(const QCString &indexName,const QValueLi
if (stack->count()>1)
{
TemplateVariant *tmp = stack->pop();
parent = *stack->top();
// To prevent a cyclic dependency between parent and child which causes a memory
// leak, we wrap the parent into a weak reference version.
parent = new TemplateStructWeakRef(stack->top()->toStruct());
stack->push(tmp);
ASSERT(parent.type()==TemplateVariant::Struct);
}
Expand Down Expand Up @@ -3652,6 +3676,7 @@ class TemplateNodeTree : public TemplateNodeCreator<TemplateNodeTree>
}
}
c->pop();
delete it;
return result.data();
}
void render(FTextStream &ts, TemplateContext *c)
Expand Down Expand Up @@ -4058,6 +4083,11 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
parser->removeNextToken(); // skip over endmarkers
TRACE(("}TemplateNodeMarkers(%s)\n",data.data()));
}
~TemplateNodeMarkers()
{
delete m_listExpr;
delete m_patternExpr;
}
void render(FTextStream &ts, TemplateContext *c)
{
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
Expand Down Expand Up @@ -4109,6 +4139,7 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
}
ts << str.right(str.length()-index); // write text after last marker
c->pop();
delete it;
}
else
{
Expand Down Expand Up @@ -4770,6 +4801,11 @@ TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const QCS
parser.parse(this,1,QStrList(),m_nodes);
}

TemplateImpl::~TemplateImpl()
{
//printf("deleting template %s\n",m_name.data());
}

void TemplateImpl::render(FTextStream &ts, TemplateContext *c)
{
TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
Expand Down

0 comments on commit d14bcd1

Please sign in to comment.