@@ -384,7 +384,8 @@ inline PyObject *read_pair_array(ReaderT *reader, TypeTreeNodeObject *node, Type
384384 Py_DECREF (list);
385385 return NULL ;
386386 }
387- PyList_SET_ITEM (list, i, PyTuple_Pack (2 , first, second));
387+ PyList_SET_ITEM (list, i, PyTuple_Pack (2 , first, second)); // pack creates two strong references
388+ // so we need to decref both values here to bring their ref count back to 1
388389 Py_DECREF (first);
389390 Py_DECREF (second);
390391 }
@@ -396,10 +397,10 @@ template <bool swap, bool as_dict>
396397inline PyObject *read_class (ReaderT *reader, TypeTreeNodeObject *node, TypeTreeReaderConfigT *config)
397398{
398399 bool changed_registry = false ;
399- PyObject *value = PyDict_New ();
400+ PyObject *value = PyDict_New (); // value: 1 refcount
400401 for (int i = 0 ; i < PyList_GET_SIZE (node->m_Children ); i++)
401402 {
402- TypeTreeNodeObject *child = (TypeTreeNodeObject *)PyList_GET_ITEM (node->m_Children , i);
403+ TypeTreeNodeObject *child = (TypeTreeNodeObject *)PyList_GET_ITEM (node->m_Children , i); // no refcount change
403404 if (child->_data_type == NodeDataType::ManagedReferencesRegistry)
404405 {
405406 if (config->has_registry )
@@ -412,29 +413,29 @@ inline PyObject *read_class(ReaderT *reader, TypeTreeNodeObject *node, TypeTreeR
412413 config->has_registry = true ;
413414 }
414415 }
415- PyObject *child_value = read_typetree_value<swap>(reader, child, config);
416+ PyObject *child_value = read_typetree_value<swap>(reader, child, config); // child_value: 1 refcount
416417 if (!child_value)
417418 {
418- Py_DECREF (value);
419+ Py_DECREF (value); // value: 0 refcount
419420 return NULL ;
420421 }
421422 int set_item_result;
422423 if constexpr (as_dict == true )
423424 {
424- set_item_result = PyDict_SetItem (value, child->m_Name , child_value);
425+ set_item_result = PyDict_SetItem (value, child->m_Name , child_value); // child_value: 2 refcount
425426 }
426427 else
427428 {
428- set_item_result = PyDict_SetItem (value, child->_clean_name , child_value);
429+ set_item_result = PyDict_SetItem (value, child->_clean_name , child_value); // child_value: 2 refcount
429430 }
430431 if (set_item_result != 0 )
431432 {
432- Py_DECREF (value);
433- Py_DECREF (child_value);
433+ Py_DECREF (value); // value: 0 refcount
434+ Py_DECREF (child_value); // child_value: 0 refcount
434435 return NULL ;
435436 }
436437 // PyDict_SetItem increases ref count, so we need to decref here
437- Py_DECREF (child_value);
438+ Py_DECREF (child_value); // child_value: 1 refcount
438439 }
439440
440441 if (changed_registry)
@@ -1033,6 +1034,7 @@ static void TypeTreeNode_dealloc(TypeTreeNodeObject *self)
10331034 Py_XDECREF (self->m_MetaFlag );
10341035 Py_XDECREF (self->m_RefTypeHash );
10351036 Py_XDECREF (self->m_Children );
1037+ Py_XDECREF (self->_clean_name );
10361038 Py_TYPE (self)->tp_free ((PyObject *)self);
10371039}
10381040
@@ -1129,6 +1131,7 @@ static int TypeTreeNode_init(TypeTreeNodeObject *self, PyObject *args, PyObject
11291131 self->m_Index = nullptr ;
11301132 self->m_MetaFlag = nullptr ;
11311133 self->m_RefTypeHash = nullptr ;
1134+ self->_clean_name = nullptr ;
11321135
11331136 if (!PyArg_ParseTupleAndKeywords (args, kwargs, " O!O!O!O!O!|O!O!O!O!O!O!" , (char **)kwlist,
11341137 // required fields
@@ -1176,7 +1179,7 @@ static int TypeTreeNode_init(TypeTreeNodeObject *self, PyObject *args, PyObject
11761179
11771180 std::string sname = PyUnicode_AsUTF8 (self->m_Name );
11781181 std::string sclean_name = clean_name (sname);
1179- self->_clean_name = PyUnicode_FromString (sclean_name.c_str ());
1182+ self->_clean_name = PyUnicode_FromString (sclean_name.c_str ()); // comes with strong ref
11801183 return 0 ;
11811184}
11821185
0 commit comments