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:
@@ -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;
|
||||
|
||||
@@ -458,6 +458,8 @@ private:
|
||||
/// Destructor
|
||||
virtual ~Application();
|
||||
|
||||
static void cleanupUnits();
|
||||
|
||||
/** @name member for parameter */
|
||||
//@{
|
||||
static ParameterManager *_pcSysParamMngr;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -240,6 +240,7 @@ private:
|
||||
*/
|
||||
|
||||
ReportOutputObserver::ReportOutputObserver(ReportOutput *report)
|
||||
: QObject(report)
|
||||
{
|
||||
this->reportView = report;
|
||||
}
|
||||
|
||||
@@ -83,6 +83,9 @@ PropertyEditor::PropertyEditor(QWidget *parent)
|
||||
|
||||
PropertyEditor::~PropertyEditor()
|
||||
{
|
||||
QItemEditorFactory* f = delegate->itemEditorFactory();
|
||||
delegate->setItemEditorFactory(nullptr);
|
||||
delete f;
|
||||
}
|
||||
|
||||
void PropertyEditor::setAutomaticExpand(bool v)
|
||||
|
||||
Reference in New Issue
Block a user