From 90ff3b6df5c6564f621e06d411ca8530fb4da61e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sat, 18 Nov 2006 22:35:03 +0100 Subject: [PATCH] Fix a memory leak when a tree is partially replaced. This situation happens when a variable of different type, but the same name is displayed at the next stop. (An expanded 'this' pointer is a common case.) In this case, the old subtree was not released. --- kdbg/dbgdriver.h | 4 +++- kdbg/debugger.cpp | 24 +++++++++--------------- kdbg/debugger.h | 1 - kdbg/exprwnd.cpp | 23 +++++++++++++++-------- kdbg/exprwnd.h | 4 +++- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/kdbg/dbgdriver.h b/kdbg/dbgdriver.h index 4ff75be..34fcc93 100644 --- a/kdbg/dbgdriver.h +++ b/kdbg/dbgdriver.h @@ -276,7 +276,6 @@ public: virtual QStringList boolOptionList() const = 0; virtual bool startup(QString cmdStr); - void dequeueCmdByVar(VarTree* var); void setLogFileName(const QString& fname) { m_logFileName = fname; } protected: @@ -569,6 +568,9 @@ protected: QString m_logFileName; QFile m_logFile; +public slots: + void dequeueCmdByVar(VarTree* var); + protected slots: virtual void slotReceiveOutput(KProcess*, char* buffer, int buflen); virtual void slotCommandRead(KProcess*); diff --git a/kdbg/debugger.cpp b/kdbg/debugger.cpp index 3c257f6..d8b9106 100644 --- a/kdbg/debugger.cpp +++ b/kdbg/debugger.cpp @@ -121,6 +121,10 @@ bool KDebugger::debugProgram(const QString& name, connect(driver, SIGNAL(inferiorRunning()), SLOT(slotInferiorRunning())); connect(driver, SIGNAL(enterIdleState()), SLOT(backgroundUpdate())); connect(driver, SIGNAL(enterIdleState()), SIGNAL(updateUI())); + connect(&m_localVariables, SIGNAL(removingItem(VarTree*)), + driver, SLOT(dequeueCmdByVar(VarTree*))); + connect(&m_watchVariables, SIGNAL(removingItem(VarTree*)), + driver, SLOT(dequeueCmdByVar(VarTree*))); // create the program settings object openProgramConfig(name); @@ -1316,8 +1320,10 @@ void KDebugger::handleLocals(const char* output) // old variable not in the new variables TRACE(QString("old var deleted: ") + n); v = m_localVariables.topLevelExprByName(n); - removeExpr(&m_localVariables, v); - if (v != 0) repaintNeeded = true; + if (v != 0) { + m_localVariables.removeExpr(v); + repaintNeeded = true; + } } else { // variable in both old and new lists: update TRACE(QString("update var: ") + n); @@ -1775,18 +1781,6 @@ void KDebugger::evalStructExpression(VarTree* var, ExprWnd* wnd, bool immediate) cmd->m_exprWnd = wnd; } -/* removes expression from window */ -void KDebugger::removeExpr(ExprWnd* wnd, VarTree* var) -{ - if (var == 0) - return; - - // must remove any references to var from command queues - m_d->dequeueCmdByVar(var); - - wnd->removeExpr(var); -} - void KDebugger::handleSharedLibs(const char* output) { // delete all known libraries @@ -1865,7 +1859,7 @@ void KDebugger::slotDeleteWatch() if (m_watchEvalExpr.findRef(item) >= 0) { m_watchEvalExpr.remove(); } - removeExpr(&m_watchVariables, item); + m_watchVariables.removeExpr(item); // item is invalid at this point! } diff --git a/kdbg/debugger.h b/kdbg/debugger.h index 8712462..a0a2aae 100644 --- a/kdbg/debugger.h +++ b/kdbg/debugger.h @@ -373,7 +373,6 @@ protected: void exprExpandingHelper(ExprWnd* wnd, KTreeViewItem* item, bool& allow); void dereferencePointer(ExprWnd* wnd, VarTree* var, bool immediate); void determineType(ExprWnd* wnd, VarTree* var); - void removeExpr(ExprWnd* wnd, VarTree* var); void queueMemoryDump(bool immediate); CmdQueueItem* loadCoreFile(); void openProgramConfig(const QString& name); diff --git a/kdbg/exprwnd.cpp b/kdbg/exprwnd.cpp index e3885ba..c980462 100644 --- a/kdbg/exprwnd.cpp +++ b/kdbg/exprwnd.cpp @@ -472,12 +472,13 @@ void ExprWnd::replaceChildren(VarTree* display, VarTree* newValues) ASSERT(display->childCount() == 0 || display->m_varKind != VarTree::VKsimple); // delete all children of display - KTreeViewItem* c; - while ((c = display->getChild()) != 0) { + while (VarTree* c = static_cast(display->getChild())) { + unhookSubtree(c); display->removeChild(c); + delete c; } // insert copies of the newValues - for (c = newValues->getChild(); c != 0; c = c->getSibling()) { + for (KTreeViewItem* c = newValues->getChild(); c != 0; c = c->getSibling()) { VarTree* v = static_cast(c); VarTree* vNew = new VarTree(v->getText(), v->m_nameKind); vNew->m_varKind = v->m_varKind; @@ -579,10 +580,7 @@ VarTree* ExprWnd::memberByName(VarTree* v, const QString& name) void ExprWnd::removeExpr(VarTree* item) { - // must remove any pointers scheduled for update from the list - sweepList(m_updatePtrs, item); - sweepList(m_updateType, item); - sweepList(m_updateStruct, item); + unhookSubtree(item); takeItem(item); delete item; @@ -590,7 +588,16 @@ void ExprWnd::removeExpr(VarTree* item) updateValuesWidth(); } -void ExprWnd::sweepList(QList& list, VarTree* subTree) +void ExprWnd::unhookSubtree(VarTree* subTree) +{ + // must remove any pointers scheduled for update from the list + unhookSubtree(m_updatePtrs, subTree); + unhookSubtree(m_updateType, subTree); + unhookSubtree(m_updateStruct, subTree); + emit removingItem(subTree); +} + +void ExprWnd::unhookSubtree(QList& list, VarTree* subTree) { if (subTree == 0) return; diff --git a/kdbg/exprwnd.h b/kdbg/exprwnd.h index 699604f..5ab165b 100644 --- a/kdbg/exprwnd.h +++ b/kdbg/exprwnd.h @@ -132,12 +132,14 @@ protected: ValueEdit m_edit; /** remove items that are in the subTree from the list */ - static void sweepList(QList& list, VarTree* subTree); + void unhookSubtree(VarTree* subTree); + static void unhookSubtree(QList& list, VarTree* subTree); protected slots: void slotExpandOrCollapse(int); signals: + void removingItem(VarTree*); void editValueCommitted(int, const QString&); }; -- 2.11.4.GIT