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<wchar_t*> 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
This commit is contained in:
wmayer
2021-02-27 10:56:19 +01:00
parent 6584c6e2ac
commit dd4dd204d0
8 changed files with 41 additions and 11 deletions

View File

@@ -340,7 +340,6 @@ Application::Application(std::map<std::string,std::string> &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;

View File

@@ -458,6 +458,8 @@ private:
/// Destructor
virtual ~Application();
static void cleanupUnits();
/** @name member for parameter */
//@{
static ParameterManager *_pcSysParamMngr;

View File

@@ -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;

View File

@@ -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<wchar_t *> _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

View File

@@ -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();

View File

@@ -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;

View File

@@ -240,6 +240,7 @@ private:
*/
ReportOutputObserver::ReportOutputObserver(ReportOutput *report)
: QObject(report)
{
this->reportView = report;
}

View File

@@ -83,6 +83,9 @@ PropertyEditor::PropertyEditor(QWidget *parent)
PropertyEditor::~PropertyEditor()
{
QItemEditorFactory* f = delegate->itemEditorFactory();
delegate->setItemEditorFactory(nullptr);
delete f;
}
void PropertyEditor::setAutomaticExpand(bool v)