Release of references in PyObject when that object is a dictionary, list or text string

51 views Asked by At

I have a code in Python C API like this:

PyObject* result = PyObject_CallMethod(/* some function with some arguments */);
// Do something with result
Py_XDECREF(result);

I'm almost sure this code is fine from the point of view of references releasing when result is a PyObject* representing a simple type (PyBool, PyLong, PyFloat, etc.) but I'm unsure in the following cases:

  1. Dictionaries (i.e. result is of PyDict type)
  2. Lists (i.e. result is of PyList type)
  3. Text strings (i.e. result is of PyUnicodeObject type)

(In case 1 and 2 my doubt is due to dictionaries/lists also use PyObject* for it's members and I'm not sure if Py_XDECREF() is smart enough to remove all references used internally in the dictionary/list or if I have to implement some kind of recursive removal function)

Is my approach right also for these types?

EDIT: to answer the question in the comment is the code you are using making references to the objects that are referenced by the dict or list? a closer version to reality is the following one.

As you can see, the processing of the result is done in a recursive way. Not sure if key, value and the result of PyList_GetItem(result, ix) are making references that should be freed in some way...

void process(PyObject* result) {
  if (PyDict_Check(result)) {
    PyObject *key, *value;
    Py_ssize_t pos = 0;
    while (PyDict_Next(value, &pos, &key, &value)) {
      process(value);
    }
  } else if (PyList_Check(result)) {
    Py_ssize_t size = PyList_Size(result);
    for (Py_ssize_t ix = 0; ix < size; ++ix) {
      process(PyList_GetItem(result, ix));
    }
  } else if (PyUnicode_Check(result)) {
    const char* str = PyUnicode_AsUTF8(result);
    // do something with str
  } else {
    // processing other types
}

// code entry point
PyObject* result = PyObject_CallMethod(/* some function with some arguments */);
process(result);
Py_XDECREF(result);
0

There are 0 answers