[Bf-blender-cvs] [f5e020a] master: PyAPI: fix memory leaks in dictionary assignment

Campbell Barton noreply at git.blender.org
Thu Jul 14 09:28:09 CEST 2016


Commit: f5e020a7a6ad6451fcaf075ae14f7014b8a4faea
Author: Campbell Barton
Date:   Thu Jul 14 17:28:28 2016 +1000
Branches: master
https://developer.blender.org/rBf5e020a7a6ad6451fcaf075ae14f7014b8a4faea

PyAPI: fix memory leaks in dictionary assignment

Thanks to Kévin Dietrich for spotting driver leak,
checked other uses of PyDict_SetItem and found more.

===================================================================

M	source/blender/python/generic/py_capi_utils.c
M	source/blender/python/intern/bpy_app.c
M	source/blender/python/intern/bpy_driver.c
M	source/blender/python/intern/bpy_library_load.c
M	source/gameengine/GameLogic/SCA_PythonController.cpp
M	source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
M	source/gameengine/GameLogic/SCA_PythonMouse.cpp

===================================================================

diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 7f13a7a..8b741eb 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -748,6 +748,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
 		
 		/* set the value so we can access it */
 		PyDict_SetItemString(py_dict, "values", values);
+		Py_DECREF(values);
 
 		py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict);
 
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 17617a2..93c97d4 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -356,10 +356,10 @@ static PyGetSetDef bpy_app_getsets[] = {
 static void py_struct_seq_getset_init(void)
 {
 	/* tricky dynamic members, not to py-spec! */
-	PyGetSetDef *getset;
-
-	for (getset = bpy_app_getsets; getset->name; getset++) {
-		PyDict_SetItemString(BlenderAppType.tp_dict, getset->name, PyDescr_NewGetSet(&BlenderAppType, getset));
+	for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
+		PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
+		PyDict_SetItemString(BlenderAppType.tp_dict, getset->name, item);
+		Py_DECREF(item);
 	}
 }
 /* end dynamic bpy.app */
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index 9b477e3..65b6bd5 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -110,9 +110,11 @@ static void bpy_pydriver_update_dict(const float evaltime)
 			bpy_pydriver_InternStr__frame = PyUnicode_FromString("frame");
 		}
 
+		PyObject *item = PyFloat_FromDouble(evaltime);
 		PyDict_SetItem(bpy_pydriver_Dict,
 		               bpy_pydriver_InternStr__frame,
-		               PyFloat_FromDouble(evaltime));
+		               item);
+		Py_DECREF(item);
 
 		bpy_pydriver_evaltime_prev = evaltime;
 	}
@@ -301,7 +303,10 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
 
 		/* try to add to dictionary */
 		/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
-		if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) {
+		if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) {
+			Py_DECREF(driver_arg);
+		}
+		else {
 			/* this target failed - bad name */
 			if (targets_ok) {
 				/* first one - print some extra info for easier identification */
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index a120e48..9c417cf 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -264,8 +264,13 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args))
 			if (BKE_idcode_is_linkable(code)) {
 				const char *name_plural = BKE_idcode_to_name_plural(code);
 				PyObject *str = PyUnicode_FromString(name_plural);
-				PyDict_SetItem(self->dict, str, PyList_New(0));
-				PyDict_SetItem(from_dict, str, _bpy_names(self, code));
+				PyObject *item;
+
+				PyDict_SetItem(self->dict, str, item = PyList_New(0));
+				Py_DECREF(item);
+				PyDict_SetItem(from_dict, str, item = _bpy_names(self, code));
+				Py_DECREF(item);
+
 				Py_DECREF(str);
 			}
 		}
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index 25936b3..fd2e723 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -163,7 +163,9 @@ void SCA_PythonController::SetNamespace(PyObject*	pythondictionary)
 	
 	/* Without __file__ set the sys.argv[0] is used for the filename
 	 * which ends up with lines from the blender binary being printed in the console */
-	PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_From_STR_String(m_scriptName));
+	PyObject *value = PyUnicode_From_STR_String(m_scriptName);
+	PyDict_SetItemString(m_pythondictionary, "__file__", value);
+	Py_DECREF(value);
 	
 }
 #endif
diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
index 19aae46..9a96a7b 100644
--- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
@@ -113,11 +113,15 @@ PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU
 {
 	SCA_PythonKeyboard* self = static_cast<SCA_PythonKeyboard*>(self_v);
 	
-	for (int i=SCA_IInputDevice::KX_BEGINKEY; i<=SCA_IInputDevice::KX_ENDKEY; i++)
-	{
+	for (int i = SCA_IInputDevice::KX_BEGINKEY; i <= SCA_IInputDevice::KX_ENDKEY; i++) {
 		const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
-		
-		PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+		PyObject *key   = PyLong_FromLong(i);
+		PyObject *value = PyLong_FromLong(inevent.m_status);
+
+		PyDict_SetItem(self->m_event_dict, key, value);
+
+		Py_DECREF(key);
+		Py_DECREF(value);
 	}
 	Py_INCREF(self->m_event_dict);
 	return self->m_event_dict;
@@ -129,12 +133,18 @@ PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PY
 
 	PyDict_Clear(self->m_event_dict);
 	
-	for (int i=SCA_IInputDevice::KX_BEGINKEY; i<=SCA_IInputDevice::KX_ENDKEY; i++)
-	{
+	for (int i = SCA_IInputDevice::KX_BEGINKEY; i <= SCA_IInputDevice::KX_ENDKEY; i++) {
 		const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
 		
-		if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
-			PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+		if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) {
+			PyObject *key   = PyLong_FromLong(i);
+			PyObject *value = PyLong_FromLong(inevent.m_status);
+
+			PyDict_SetItem(self->m_event_dict, key, value);
+
+			Py_DECREF(key);
+			Py_DECREF(value);
+		}
 	}
 	Py_INCREF(self->m_event_dict);
 	return self->m_event_dict;
diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp
index 1617f71..184b306 100644
--- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp
@@ -96,11 +96,15 @@ PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_
 {
 	SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v);
 	
-	for (int i=SCA_IInputDevice::KX_BEGINMOUSE; i<=SCA_IInputDevice::KX_ENDMOUSE; i++)
-	{
-		const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
-		
-		PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+	for (int i = SCA_IInputDevice::KX_BEGINMOUSE; i <= SCA_IInputDevice::KX_ENDMOUSE; i++) {
+		const SCA_InputEvent &inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
+		PyObject *key   = PyLong_FromLong(i);
+		PyObject *value = PyLong_FromLong(inevent.m_status);
+
+		PyDict_SetItem(self->m_event_dict, key, value);
+
+		Py_DECREF(key);
+		Py_DECREF(value);
 	}
 	Py_INCREF(self->m_event_dict);
 	return self->m_event_dict;
@@ -112,12 +116,19 @@ PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT
 
 	PyDict_Clear(self->m_event_dict);
 	
-	for (int i=SCA_IInputDevice::KX_BEGINMOUSE; i<=SCA_IInputDevice::KX_ENDMOUSE; i++)
-	{
-		const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
+	for (int i = SCA_IInputDevice::KX_BEGINMOUSE; i <= SCA_IInputDevice::KX_ENDMOUSE; i++) {
+		const SCA_InputEvent &inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
 		
-		if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
-			PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+		if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) {
+
+			PyObject *key   = PyLong_FromLong(i);
+			PyObject *value = PyLong_FromLong(inevent.m_status);
+
+			PyDict_SetItem(self->m_event_dict, key, value);
+
+			Py_DECREF(key);
+			Py_DECREF(value);
+		}
 	}
 	Py_INCREF(self->m_event_dict);
 	return self->m_event_dict;




More information about the Bf-blender-cvs mailing list