Skip to content

Instantly share code, notes, and snippets.

@tnakazato
Last active November 15, 2021 07:54
Show Gist options
  • Save tnakazato/e3c29e92769be921994cd6e04e7b134f to your computer and use it in GitHub Desktop.
Save tnakazato/e3c29e92769be921994cd6e04e7b134f to your computer and use it in GitHub Desktop.
pydict-setitem #python #c-api

How PyDict_SetItem handles a reference to key

Python function PyDict_SetItem is used to insert a value val into the dictionary with a key of key. According to the API document, PyDict_SetItem does not steal a reference to val so that the caller of PyDict_SetItem keeps an ownership of val. Hence, a reference to val must be decremented after it is added to the dictionary. But there is no mention about key in the API document. What should we do for key?

PyObject *dict = PyDict_New();
PyObject *key = PyUnicode_FromString("key");
PyObject *val = PyLong_FromLong(0L);

PyDict_SetItem(dict, key, val);
Py_DECREF(val); // reference to val must be decremented
// what about key?

My conclusion is that PyDict_SetItem does not steal a reference to key either. You need to decrement a reference to key as well.

Py_DECREF(key); // reference to key must be decremented as well

It means that the following code causes memory leak.

// You have a key string
char const *another_key = "another_key";
// This is WRONG!
PyDict_SetItem(dict, PyUnicode_FromString(another_key), another_val);
Py_DECREF(another_val);

If you have a key string, PyDict_SetItemString would be useful.

// You have a key string
char const *yet_another_key = "yet_another_key";
// This is CORRECT!
PyDict_SetItemString(dict, yet_another_key, yet_another_val);
Py_DECREF(yet_another_val);

Reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment