From dd4dd204d04ce8250a49960449f3fe319940fd9c Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 27 Feb 2021 10:56:19 +0100 Subject: [PATCH] App/Gui: fix memory leaks: + add function to cleanup units and quantities in debug build + fix reference leak in PropertyVector::getPyPathValue() + fix reference leak in PropertyPlacement::getPyPathValue() + in InterpreterSingleton::init() use a static std::vector instead of a C array to free memory at program end + in MainWindow::closeEvent() explicitly delete all task watchers + in ReportOutputObserver constructor pass parent to QObject + in PropertyEditor destructor explicitly delete QItemEditorFactory --- src/App/Application.cpp | 23 ++++++++++++++++++++++- src/App/Application.h | 2 ++ src/App/PropertyGeo.cpp | 14 +++++++------- src/Base/Interpreter.cpp | 4 ++-- src/Gui/Application.cpp | 1 - src/Gui/MainWindow.cpp | 4 ++++ src/Gui/ReportView.cpp | 1 + src/Gui/propertyeditor/PropertyEditor.cpp | 3 +++ 8 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index e5cb6029fa..2f6bb886b0 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -340,7 +340,6 @@ Application::Application(std::map &mConfig) // Translate module PyObject* pTranslateModule = (new Base::Translate)->module().ptr(); - Py_INCREF(pTranslateModule); PyModule_AddObject(pAppModule, "Qt", pTranslateModule); //insert Units module @@ -1499,6 +1498,23 @@ int Application::_argc; char ** Application::_argv; +void Application::cleanupUnits() +{ + try { + Base::PyGILStateLocker lock; + Py::Module mod (Py::Module("FreeCAD").getAttr("Units").ptr()); + + Py::List attr(mod.dir()); + for (Py::List::iterator it = attr.begin(); it != attr.end(); ++it) { + mod.delAttr(Py::String(*it)); + } + } + catch (Py::Exception& e) { + Base::PyGILStateLocker lock; + e.clear(); + } +} + void Application::destruct(void) { // saving system parameter @@ -1529,6 +1545,11 @@ void Application::destruct(void) _pcSysParamMngr = 0; _pcUserParamMngr = 0; +#ifdef FC_DEBUG + // Do this only in debug mode for memory leak checkers + cleanupUnits(); +#endif + // not initialized or double destruct! assert(_pcSingleton); delete _pcSingleton; diff --git a/src/App/Application.h b/src/App/Application.h index 317d4ca9a1..506c3a364e 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -458,6 +458,8 @@ private: /// Destructor virtual ~Application(); + static void cleanupUnits(); + /** @name member for parameter */ //@{ static ParameterManager *_pcSysParamMngr; diff --git a/src/App/PropertyGeo.cpp b/src/App/PropertyGeo.cpp index 85a0b962ce..e6d1a20064 100644 --- a/src/App/PropertyGeo.cpp +++ b/src/App/PropertyGeo.cpp @@ -225,11 +225,11 @@ bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &re std::string p = path.getSubPathStr(); if (p == ".x") { - res = new QuantityPy(new Quantity(getValue().x,unit)); + res = Py::asObject(new QuantityPy(new Quantity(getValue().x,unit))); } else if(p == ".y") { - res = new QuantityPy(new Quantity(getValue().y,unit)); + res = Py::asObject(new QuantityPy(new Quantity(getValue().y,unit))); } else if(p == ".z") { - res = new QuantityPy(new Quantity(getValue().z,unit)); + res = Py::asObject(new QuantityPy(new Quantity(getValue().z,unit))); } else return false; return true; @@ -678,13 +678,13 @@ bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object if (p == ".Rotation.Angle") { Base::Vector3d axis; double angle; _cPos.getRotation().getValue(axis,angle); - res = new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle)); + res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle))); } else if (p == ".Base.x") { - res = new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length)); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length))); } else if (p == ".Base.y") { - res = new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length)); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length))); } else if (p == ".Base.z") { - res = new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length)); + res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length))); } else return false; return true; diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index b4642fb89b..369c347902 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -587,7 +587,7 @@ const char* InterpreterSingleton::init(int argc,char *argv[]) #if PY_MAJOR_VERSION >= 3 size_t size = argc; - wchar_t **_argv = new wchar_t*[size]; + static std::vector _argv(size); for (int i = 0; i < argc; i++) { #if PY_MINOR_VERSION >= 5 _argv[i] = Py_DecodeLocale(argv[i],NULL); @@ -595,7 +595,7 @@ const char* InterpreterSingleton::init(int argc,char *argv[]) _argv[i] = _Py_char2wchar(argv[i],NULL); #endif } - PySys_SetArgv(argc, _argv); + PySys_SetArgv(argc, _argv.data()); #else PySys_SetArgv(argc, argv); #endif diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index f0b4c55c1d..a62bf3a20a 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -450,7 +450,6 @@ Application::Application(bool GUIenabled) // PySide additions PySideUicModule* pySide = new PySideUicModule(); - Py_INCREF(pySide->module().ptr()); PyModule_AddObject(module, "PySideUic", pySide->module().ptr()); ExpressionBindingPy::init_type(); diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index b796e01bba..c819c57797 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -1193,6 +1193,10 @@ void MainWindow::closeEvent (QCloseEvent * e) (*it)->hide(); (*it)->deleteLater(); } + + if (Workbench* wb = WorkbenchManager::instance()->active()) + wb->removeTaskWatcher(); + d->activityTimer->stop(); saveWindowSettings(); delete d->assistant; diff --git a/src/Gui/ReportView.cpp b/src/Gui/ReportView.cpp index f68eae7658..6c90bd5266 100644 --- a/src/Gui/ReportView.cpp +++ b/src/Gui/ReportView.cpp @@ -240,6 +240,7 @@ private: */ ReportOutputObserver::ReportOutputObserver(ReportOutput *report) + : QObject(report) { this->reportView = report; } diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index a48c53a410..9bfc78639e 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -83,6 +83,9 @@ PropertyEditor::PropertyEditor(QWidget *parent) PropertyEditor::~PropertyEditor() { + QItemEditorFactory* f = delegate->itemEditorFactory(); + delegate->setItemEditorFactory(nullptr); + delete f; } void PropertyEditor::setAutomaticExpand(bool v)