Py_XDECREF/Py_DECREF evaluating its argument more than once

Chris Angelico rosuav at gmail.com
Thu May 5 20:51:33 EDT 2011


Okay, this is mainly a tale of a stupid C++ programmer who forgot the
rules of C...

I simplified a whole lot of code recently, cut out some temporary
variables, did some general tidying-up, and then found that my program
was segfaulting occasionally. Sure that I hadn't made any substantive
changes, I went tinkering, and pinned it down to this change:

Old code:
PyObject *v=PyRun_StringFlags(code,Py_file_input,py_globals,locals,0);
if (v) Py_DECREF(v);

New code:

Py_XDECREF(PyRun_StringFlags(code,Py_file_input,py_globals,locals,0));

It's the same, right? Py_XDECREF is just Py_DECREF with a check
against null? No and whoops. DEC and XDEC are both implemented as
*macros* and they evaluate their arguments more than once. (I'm not
entirely sure of the cause of the segfault, but I'm guessing that the
two runs of the code produced different results, or something. Not
significant.)

Would it be possible at some point to have them implemented as inline
functions instead? At the top of my code, I just forced it thus:

#undef Py_XDECREF
inline void Py_XDECREF(PyObject *ob) {if (ob) Py_DECREF(ob);}

Failing that, a warning note on the docs would be nice, but I'm
guessing that idiots like me wouldn't think to read it. (Or if "idiot"
is too strong, try "guy who's been spoiled by C++'s luxury".)

Fortunately for my career, solving this self-created problem didn't
take long, and my boss didn't even know about it till I'd solved it.
*whoops*

Just figured it might be worth mentioning, in case someone else is
tempted to take a shortcut!

Chris Angelico



More information about the Python-list mailing list