[Python-Dev] [Python 2.4] PyInt_FromLong returning NULL
Tim Peters
tim.peters at gmail.com
Tue Dec 7 21:25:06 CET 2004
>>> if (! PyInt_Check(p))
>>> {
>>> if (PyDict_Check(p))
>>> {
>>> if (PyString_Check(name) || PyUnicode_Check(name))
>>> {
>>> ASSIGN(p, PyObject_GetItem(p, name));
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
>>> if (p == NULL) {
>>> puts("PyObject returned NULL");
>>> PyErr_Clear();
>>> }
>>> }
>>> else
>>> p = PyInt_FromLong((long)1);
>>>
[Tim]
>> I note that all of this is nested inside another "if (p) {...}" block.
>> That implies the "p = PyInt_FromLong((long)1);" line is at least a
>> memory leak: it overwrites p without decref'ing p first.
[Jim]
> The ASSIGN macro DECREFs it's first argument if it is non-NULL.
>
> It loosly models a Python assignment, assuming that it owns the
> reference to the second argument.
ASSIGN isn't executed on the path in question. I really can't follow
nesting with that indentation style. Reformatting in Python style
makes it obvious to me:
if (p) {
if (! PyInt_Check(p)) {
if (PyDict_Check(p)) {
if (PyString_Check(name) || PyUnicode_Check(name)) {
ASSIGN(p, PyObject_GetItem(p, name));
if (p == NULL)
PyErr_Clear();
}
else
p = PyInt_FromLong(1);
}
else {
ASSIGN(p, callfunction2(p, name, value));
if (p == NULL)
goto err;
}
}
}
"p = PyInt_FromLong(1)" is in an ``else`` block. The only ASSIGN
before it is in that ``else`` block's disjoint ``if`` block.
More information about the Python-Dev
mailing list