Reputation: 6549
The following code works fine and prints out an empty list (on python3.4
):
import gc
# code interfacing with C and cython
print(gc.garbage, flush=True)
Appending this line to the very end makes it segfault:
gc.collect()
It seems like it is pure luck that the automatic collection does not happen on its own (it took me some time to get reproducible error). The collection is not ran at "end of program" either because I am running this interactively.
Some googling led me to believe that some of the C/Cython code is creating/destroying objects without telling python that those objects are already removed from memory. Then python tries to remove them and crashes.
How can I find what those objects are? I thought that they would be in gc.garbage
before the crash inducing gc.collect()
?
Or are my assumptions completely incorrect?
Prepending an gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_LEAK)
to this code leads to a python exception instead of a segfault.
---> print(gc.garbage, flush=True)
gc.collect()
...
ReferenceError: weakly-referenced object no longer exists
Edit: changed/simplified after comments from one of the answers
Upvotes: 0
Views: 1904
Reputation: 280456
You're probably misunderstanding both gc.garbage
and gc.disable()
. gc.disable()
turns off the cyclic garbage collector, leaving only reference-counting memory management active. There isn't some separate "garbage detector" that keeps detecting cyclic trash even when the garbage collector is turned off; garbage detection is the garbage collector's job.
Also, gc.garbage
is only populated with specific kinds of weird garbage the GC couldn't clear. Most garbage never ends up there.
As for how you'd go about debugging this, I'm not familiar with the tools you'd use. Generic tools like Valgrind would probably be useful, and GC flags like gc.DEBUG_LEAK
might help.
Upvotes: 1