[Python-Dev] Problem with _PyTrash_destroy_chain ?
"Martin v. Löwis"
martin at v.loewis.de
Fri Aug 31 00:21:54 CEST 2012
Am 30.08.12 22:22, schrieb Manu:
> That's right, sorry. The reason why I think this is a double free is
> that the op seems to point to an object that has been deallocated by python.
>
> (gdb) select-frame 0
> (gdb) print *op
> $6 = {_ob_next = 0x0, _ob_prev = 0x0, ob_refcnt = 0, ob_type = 0x2364020}
Doesn't look like that to me. If it was deallocated, the debug malloc
would fill it with DEADBYTE (0xDB). So the memory has *not* been
deallocated (yet?). The object was just unlinked from the all-objects
list (or the pointers were overwritten with NULL by some buggy code
of yours).
If the object had properly been unlinked before, its refcount would have
been set to 0. In turn, the DECREF call that caused the second
deallocation would have complained "UNREF negative refcnt" just above
the line where it crashed.
So it's rather unlikely that an earlier ForgetReference had happened,
unless someone has INCREFed the object again in-between. This is
actually plausible: the trashcan defers deallocation, allowing for
a double drop-refcount-to-zero operation. Without the trashcan, the
object gets deallocated, the refcount overwritten with DEADBYTE, the
bogus INCREF and the second DECREF happen, the refcount isn't 0 then,
so there is no second deallocation.
Since there apparently is still a reference from a frame, the first
forgetreference was actually bogus; the object shouldn't have been
released yet. So you are missing an INCREF somewhere.
> It would then be interesting to find out what object used to be there.
> Unfortunately, there is no easy way to find out (unless the crash
> always involves 0x4dc7bc0).
>
>
> Not sure why you know this address by heart ;) but the op pointer points
> exactly there in the stacktrace I posted in the bug report. I'd bet it's
> like this every time. What does it mean ?
It means that it's a deterministic failure, which is a good thing from
a debugging point of view. You can set a watchpoint on the refcount,
and watch it go 0, then 1, then 0 again. If you are unfamiliar with
watchpoints, here is the rough guide:
1. Find the address of ob_refcnt, i.e. &op->ob_refcnt. I *think*
it should be (int*)0x4dc7bc8, but please double-check.
2. watch *(int*)0x4dc7bc8
3. run, continue, continue, ...
In this form, this typically doesn't work, since the address has
typically no memory associated initially. So you need to set
a break point on a function that is called closely before the
object gets allocated, and set the watchpoint only then.
Good luck,
Martin
More information about the Python-Dev
mailing list