A lot of C code in Python uses this pattern:
Py_XDECREF(var);
var = value;
If var was holding the last strong reference to a Python object, the object finalizer is called which can call arbitrary Python code which can access the var variable which is now a dangling pointer, and so Python does just crash in this case.
The correct pattern is:
old_var = var;
var = value;
Py_XDECREF(old_var);
And Py_SETREF() can be used to make this code shorter and easier to read and maintain:
While the pattern is unsafe, maybe it's not possible to crash Python. But I prefer to replace this pattern with Py_SETREF() or Py_XSETREF() so I don't have to think about: oh, is it possible to crash Python?
Again, Py_SETREF() also makes the code shorter, easier to read and maintain.
While we are here, I also propose to replace:
Py_XDECREF(var);
var = NULL;
with:
which is shorter than:
See also issue #99300 "Replace Py_INCREF()/Py_XINCREF() usage with Py_NewRef()/Py_XNewRef()" and issue #99481 "Add Py_HOLD_REF() macro to hold a strong reference to a Python object while executing code".
Linked PRs
A lot of C code in Python uses this pattern:
If var was holding the last strong reference to a Python object, the object finalizer is called which can call arbitrary Python code which can access the var variable which is now a dangling pointer, and so Python does just crash in this case.
The correct pattern is:
And Py_SETREF() can be used to make this code shorter and easier to read and maintain:
While the pattern is unsafe, maybe it's not possible to crash Python. But I prefer to replace this pattern with Py_SETREF() or Py_XSETREF() so I don't have to think about: oh, is it possible to crash Python?
Again, Py_SETREF() also makes the code shorter, easier to read and maintain.
While we are here, I also propose to replace:
with:
which is shorter than:
See also issue #99300 "Replace Py_INCREF()/Py_XINCREF() usage with Py_NewRef()/Py_XNewRef()" and issue #99481 "Add Py_HOLD_REF() macro to hold a strong reference to a Python object while executing code".
Linked PRs