Comments (6)
b 在 unreachable
中而不是 finalizers
中, 你截取的代码是处理 finalizers
而不是处理 unreachable
的, 我们可以只关注处理 unreachable
的部分
通常情况下 finalizers
列表为空
finalizers
存储的是定义了 老式的析构函数 的对象, python3.4 以后的 析构函数(默认的__del__
) 是映射到 C语言中的结构体中的 tp_finalize
字段上的, 而之前的版本是 映射到了 tp_del
字段上, 所以只有以前写的 C 扩展定义了 tp_del
的对象在进行垃圾回收时, 才有可能进到 finalizers
中, 默认情况下 finalizers
就是空的, 你上面截出的函数把它放到 gc.garbage
列表中不进行处理是对的(参考 PEP 442)
unreachable
中的对象 b 在 finalize_garbage(&unreachable);
中调用了 __del__
之后就变成可达对象了, 会导致在 if (check_garbage(&unreachable))
判断为真, 本轮 a1, a2, a3, b
都不回收, 下一轮回收时 a1, a2
就被正常回收, a3, b
不回收
from cpython-internals.
看 finalize_garbage(&unreachable)
中的代码 实现了__del__
的对象 引用计数会加1, 且如您所说 _gc_prev 上的第一个 bit flag 会被设置, a3, b 不回收,这么说的话 a3, b 会一直在内存中? 并没有被回收,在官方文档也看到官方警告 也不推荐使用__del__
方法,当解释器退出时不会确保为仍然存在的对象调用 del() 方法。
还有一个疑惑,官方文档说在 3.4 版更改: 根据 PEP 442 ,带有 del() 方法的对象最终不再会进入 gc.garbage ,但就上面代码来看
/* Handle uncollectable garbage (cycles with tp_del slots, and stuff reachable
* only from such cycles).
* If DEBUG_SAVEALL, all objects in finalizers are appended to the module
* garbage list (a Python list), else only the objects in finalizers with
* __del__ methods are appended to garbage. All objects in finalizers are
* merged into the old list regardless.
* Returns 0 if all OK, <0 on error (out of memory to grow the garbage list).
* The finalizers list is made empty on a successful return.
*/
If DEBUG_SAVEALL, all objects in finalizers are appended to the module
- garbage list (a Python list), else only the objects in finalizers with
- del methods are appended to garbage.
这里是不是有点冲突了?
from cpython-internals.
官方警告似乎没有看到 不推荐使用 __del__
方法的表述?
示例代码 中当前的 namespace 中有 a3, a3 里面有 b, 那么只要我还保留着 a3 的引用, a3 和 b 就会一直在内存中, 如果我不需要 a3 了, 下一轮垃圾回收的时候 a3 和 b 就会回收
你贴的这段代码注释(按我)理解是 finalizers
中的所有对象中只有自定义了 __del__
方法的对象会被放到 gc. garbage
中, 如果你开启了 gc.set_debug(gc.DEBUG_SAVEALL)
开关的话, finalizers
中所有的对象(即使没有自定义__del__
)也会被放到 gc. garbage
中
但是你为什么要一直纠结 finalizers
这个列表呢
b 显式的定义了 __del__
, b 在 unreachable
这个列表中, 不在 finalizers
中
a1, a2, a3 都没有定义 __del__
, a1, a2, a3 也还是在 unreachable
这个列表中, 不在 finalizers
中
所以不论定义没定义 __del__
, 这些对象都只可能出现在 unreachable
列表中, 不会出现在 finalizers
中
finalizers
列表从开始到结束都是空列表
finalizers
的作用是把 以前用 C 写的扩展中老代码定义了 __del__
方法的对象放到 gc.garbage
中, 对这一部分对象, 延用的还是旧的不回收的处理方式
我猜测你想找的应该是处理 unreachable
这个列表的代码, 但是你找到了 finalizers
上面去了, 如果是这种情况的话你可以在中间加一些日志代码, 自己编译运行调试一下😁
from cpython-internals.
恩恩,明白了
finalizers
的作用是把 以前用 C 写的扩展中老代码定义了__del__
方法的对象放到 gc.garbage
中, 对这一部分对象, 延用的还是旧的不回收的处理方式。
明白了,还是要编译运行调试一下,就可以知道结果了,感谢大佬不吝指教,谢谢~
from cpython-internals.
有个疑惑请大神解答一下,在处理循环引用的时候,是如何判断是不是要对该对象进行gc_ref-=1的操作的?
subtract_refs 会遍历 young 中的所有对象, 对于每个对象, 检查当前对象身上所引用到的所有其他对象, 这些其他对象如果也在 young 中, 并且是可回收的对象, 把这个对象复制到 _gc_prev 的引用计数部分减1 (用 tp_traverse 遍历, 遍历回调函数为 visit_decref)
请问这句话怎么理解呢:检查当前对象身上所引用到的所有其他对象, 这些其他对象如果也在 young 中, 并且是可回收的对象?
看您的图是把young里的gc_ref都进行了减1操作,然后对于c 和 d2又进行了加一操作(我在其他文章看到说这协变量是root object)所以会检查当前变量是不是root object 如果是且被添加到了unreachable中,就将其gc_ref+1 , 并添加回yong中。
from cpython-internals.
/*
假设
A = [B, C, D]
A在代内, B也在代内, C不在, D不在
遍历A引用的对象, B在代内, B进行 gc_ref-=1
C不在, 不进行 gc_ref-=1
D不在, 不进行 gc_ref-=1
同一个代里, 对象的所有互相的引用都会触发 gc_ref-=1
下面这段代码就是你上面高亮文字部分
*/
static void
subtract_refs(PyGC_Head *containers)
{
traverseproc traverse;
PyGC_Head *gc = GC_NEXT(containers);
for (; gc != containers; gc = GC_NEXT(gc)) {
PyObject *obj = FROM_GC(gc); // #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
visit_from = obj;
traverse = Py_TYPE(FROM_GC(gc))->tp_traverse;
(void) traverse(FROM_GC(gc),
(visitproc)visit_decref,
NULL);
}
}
c
和 d2
在 subtract_refs
之后被减到了小于等于 0
static void
move_unreachable(PyGC_Head *young, PyGC_Head *unreachable)
{
// ...
while (gc != young) {
PyObject *obj = FROM_GC(gc); // #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))
if (gc_get_refs(gc)) {
/*
遍历到 namespace 的时候, 由于 namespace 还保存了 `c` 和 `d2` 的引用
visit_reachable 会把 `c` 和 `d2` 的引用计数置为 1
*/
PyObject *op = FROM_GC(gc);
traverseproc traverse = Py_TYPE(op)->tp_traverse;
// ...
visit_from = op;
(void) traverse(op,
(visitproc)visit_reachable,
(void *)young);
// ...
}
else {
// ...
}
// ...
gc = (PyGC_Head*)prev->_gc_next;
}
}
c
和 d2
在 move_unreachable
之后被重置为 1
from cpython-internals.
Related Issues (20)
- little endian and big endian HOT 1
- How to convert code in Python into C HOT 2
- Markdown code formatting HOT 1
- Cython GIL - check_interval & interval HOT 2
- Python's compile phase -- Grammar/MetaGrammar to DFA
- next是什么时候触发 `zombie`frame的 HOT 4
- 关注你这个很久了,是否考虑过弄个群? HOT 5
- Python's compile phase -- CST TO AST
- Python's compile phase -- AST to python byte code
- C++ extension(integrate with NumPy/bypass the GIL)
- 很多图挂了 HOT 3
- how pickle implemented in python3
- 图错误 HOT 1
- Interpreter/frame/frame_cn.md code->nfrees变量名问题 HOT 1
- Interpreter/frame/frame_cn.md 图片解释疑问 HOT 1
- hash("key2") % 8 is 2! HOT 3
- gc_cn.md 中 为什么 a1 和 a2 在本轮 GC 中存活了?
- the light font color in the images make it hard to read in GH dark mode.
- Updating Link for more stack frame information
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cpython-internals.