1 | n/a | """ |
---|
2 | n/a | gc.get_referrers() can be used to see objects before they are fully built. |
---|
3 | n/a | |
---|
4 | n/a | Note that this is only an example. There are many ways to crash Python |
---|
5 | n/a | by using gc.get_referrers(), as well as many extension modules (even |
---|
6 | n/a | when they are using perfectly documented patterns to build objects). |
---|
7 | n/a | |
---|
8 | n/a | Identifying and removing all places that expose to the GC a |
---|
9 | n/a | partially-built object is a long-term project. A patch was proposed on |
---|
10 | n/a | SF specifically for this example but I consider fixing just this single |
---|
11 | n/a | example a bit pointless (#1517042). |
---|
12 | n/a | |
---|
13 | n/a | A fix would include a whole-scale code review, possibly with an API |
---|
14 | n/a | change to decouple object creation and GC registration, and according |
---|
15 | n/a | fixes to the documentation for extension module writers. It's unlikely |
---|
16 | n/a | to happen, though. So this is currently classified as |
---|
17 | n/a | "gc.get_referrers() is dangerous, use only for debugging". |
---|
18 | n/a | """ |
---|
19 | n/a | |
---|
20 | n/a | import gc |
---|
21 | n/a | |
---|
22 | n/a | |
---|
23 | n/a | def g(): |
---|
24 | n/a | marker = object() |
---|
25 | n/a | yield marker |
---|
26 | n/a | # now the marker is in the tuple being constructed |
---|
27 | n/a | [tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple] |
---|
28 | n/a | print(tup) |
---|
29 | n/a | print(tup[1]) |
---|
30 | n/a | |
---|
31 | n/a | |
---|
32 | n/a | tuple(g()) |
---|