[issue6939] shadows around the io truncate() semantics
Antoine Pitrou
report at bugs.python.org
Fri Jan 15 23:15:21 CET 2010
Antoine Pitrou <pitrou at free.fr> added the comment:
> posobj = portable_lseek(fd, posobj, 0); -> don't we lose the reference
> to the old "posobj" there, doing a memory leak ?
It's a bit more subtle.
Here, the first reference to "posobj" that you get is through the
function arguments. You don't own that reference, so must not decref it
when you are done with it. Moreover, if you return that very same
reference, you should incref it first (which your patch doesn't do when
posobj is non-None, and therefore loses a reference, see below).
However, when you get a new "posobj" from portable_lseek() (or most
other C API functions), you own this new reference and therefore must
decref it when you are done with it.
To sum it up and if I'm not mistaken, you must:
- add a Py_INCREF(posobj) when posobj is non-NULL and non-None.
- Py_DECREF the first posobj, as well as oldposobj, in the
Windows-specific path.
If you wanna witness reference counting behaviour, you should build
Python in debug mode (--with-pydebug if under Linux). Right now under
Linux your patch produces the following behaviour:
[39542 refs]
>>> f.truncate()
0L
[39547 refs]
>>> f.truncate()
0L
[39547 refs]
>>> f.truncate(2)
2
[39545 refs]
>>> f.truncate(2)
2
[39544 refs]
As you see, when posobj is non-None, we actually lose a reference
because a Py_INCREF is missing.
If you do this too often the small integer object "2" gets wrongly
destroyed and the interpreter crashes:
...
[snip]
Erreur de segmentation
----------
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue6939>
_______________________________________
More information about the Python-bugs-list
mailing list