From bab4c3056c11ba3607acce3314ecfe172d00cf96 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 22 Feb 2010 17:59:59 +0100 Subject: Fix memory leak when lazily binding QScriptValue to an engine Avoid the engine's list of free script values from growing without bounds. When a QScriptValue is initially not bound, its private will be allocated from the normal heap (and not from the engine's pool of privates, because there is no engine at this point). But when a value is later bound (e.g. by setting it as a property of an object, or by passing it as argument to QScriptValue::call()) and is subsequently destroyed, its private will be handed to the engine, which will add it to its free-list (hence the memory is not freed). This allocation/deallocation asymmetry causes this list go keep growing. The solution is to limit the size of the free-list, and free the memory of the private immediately when the list has reached a certain size. Task-number: QTBUG-8400 Reviewed-by: Olivier Goffart --- src/script/api/qscriptengine.cpp | 2 +- src/script/api/qscriptengine_p.h | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 1bd7377..1199263 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -768,7 +768,7 @@ static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng) } // namespace QScript QScriptEnginePrivate::QScriptEnginePrivate() - : registeredScriptValues(0), freeScriptValues(0), + : registeredScriptValues(0), freeScriptValues(0), freeScriptValuesCount(0), registeredScriptStrings(0), inEval(false) { qMetaTypeId(); diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 6780b2c..401d6d2 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -255,6 +255,8 @@ public: int agentLineNumber; QScriptValuePrivate *registeredScriptValues; QScriptValuePrivate *freeScriptValues; + static const int maxFreeScriptValues = 256; + int freeScriptValuesCount; QScriptStringPrivate *registeredScriptStrings; QHash m_typeInfos; int processEventsInterval; @@ -377,6 +379,7 @@ inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(siz if (freeScriptValues) { QScriptValuePrivate *p = freeScriptValues; freeScriptValues = p->next; + --freeScriptValuesCount; return p; } return reinterpret_cast(qMalloc(size)); @@ -384,8 +387,13 @@ inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(siz inline void QScriptEnginePrivate::freeScriptValuePrivate(QScriptValuePrivate *p) { - p->next = freeScriptValues; - freeScriptValues = p; + if (freeScriptValuesCount < maxFreeScriptValues) { + p->next = freeScriptValues; + freeScriptValues = p; + ++freeScriptValuesCount; + } else { + qFree(p); + } } inline void QScriptEnginePrivate::registerScriptValue(QScriptValuePrivate *value) -- cgit v0.12