数组作为类成员和引用计数
有件事让我感到困惑。让有一个班员 Foo::$bar
,它必须在 构造函数。如果我这样做(通过zend_update_property
),它的引用计数是 增加(从 alloc + array_init 之后获得的 1 增加到 2)。这是 很明显为什么会发生这种情况,因为从 zend_update_property 的角度来看,它得到了 来自外部世界的变量,因此 ++ 它是正确的。
但在这种特殊情况下,数组正在初始化 构造函数,它不需要 2 的引用计数,1 是正确的,因为它是 仅由该对象使用(尚未)。
所以我想我会Z_DELREF_P()
它。它奏效了。直到我开始 valgrind,正在报告:
==4538== Invalid read of size 4
==4538== at 0x822D3C6: _zval_ptr_dtor (zend.h:385)
==4538== by 0x823C1FF: _zval_ptr_dtor_wrapper (zend_variables.c:189)
==4538== by 0x824E1A1: zend_hash_destroy (zend_hash.c:529)
==4538== by 0x826655A: zend_object_std_dtor (zend_objects.c:45)
==4538== by 0x8266A28: zend_objects_free_object_storage
(zend_objects.c:126)
==4538== by 0x826C43D: zend_objects_store_del_ref_by_handle_ex
(zend_objects_API.c:220)
==4538== by 0x826C0AC: zend_objects_store_del_ref
(zend_objects_API.c:172)
==4538== by 0x823BD77: _zval_dtor_func (zend_variables.c:52)
==4538== by 0x822B99B: _zval_dtor (zend_variables.h:35)
==4538== by 0x822D463: _zval_ptr_dtor (zend_execute_API.c:443)
==4538== by 0x823C1FF: _zval_ptr_dtor_wrapper (zend_variables.c:189)
==4538== by 0x824E518: zend_hash_apply_deleter (zend_hash.c:614)
==4538== Address 0x44c1718 is 8 bytes inside a block of size 20 free'd
当引擎销毁对象时会发生这种情况(当对象超出范围时 - 也会调用析构函数)。
所以看起来 ZE 确实需要将引用计数设置为 2。所有其他 我编写的测试工作正常,没有内存泄漏,没有任何段错误。
我仍然有点困惑:为什么它需要高于 (根据我的理解)应该是?
There is something that confuses me. Let there be a class memberFoo::$bar
, which has to be initialized as an empty array in the
constructor. If I do that (via zend_update_property
), its refcount is
increased (from 1, which it gets after alloc + array_init
, to 2). It is
obvious why this happens, since from zend_update_property
's perspective, it gets a
variable from somone in the outside world, and so it is right to ++ it.
But in this particular case, the array being initialized in the
constructor, it does not need a refcount of 2, 1 is right, since it's
used only by the object (yet).
So I thought I will Z_DELREF_P()
it. And it worked. Until I started
valgrind, which was reporting:
==4538== Invalid read of size 4
==4538== at 0x822D3C6: _zval_ptr_dtor (zend.h:385)
==4538== by 0x823C1FF: _zval_ptr_dtor_wrapper (zend_variables.c:189)
==4538== by 0x824E1A1: zend_hash_destroy (zend_hash.c:529)
==4538== by 0x826655A: zend_object_std_dtor (zend_objects.c:45)
==4538== by 0x8266A28: zend_objects_free_object_storage
(zend_objects.c:126)
==4538== by 0x826C43D: zend_objects_store_del_ref_by_handle_ex
(zend_objects_API.c:220)
==4538== by 0x826C0AC: zend_objects_store_del_ref
(zend_objects_API.c:172)
==4538== by 0x823BD77: _zval_dtor_func (zend_variables.c:52)
==4538== by 0x822B99B: _zval_dtor (zend_variables.h:35)
==4538== by 0x822D463: _zval_ptr_dtor (zend_execute_API.c:443)
==4538== by 0x823C1FF: _zval_ptr_dtor_wrapper (zend_variables.c:189)
==4538== by 0x824E518: zend_hash_apply_deleter (zend_hash.c:614)
==4538== Address 0x44c1718 is 8 bytes inside a block of size 20 free'd
which happens when the engine destroys the object (when the object runs out of scope - the destructor is also called).
So it looks like the ZE really needs the refcount to be 2. All other
tests I've written work fine, no memleaks, no segfaults whatsoever.
Still I am a little bit confused: WHY does it need it be higher than
(from my understanding) it should be?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
@hakre 的问题让我思考。
解释如下:当 ZE 销毁对象时,它也会销毁 (
zval_ptr_dtor
) 对象的每个属性。因此,在调用析构函数后将引用计数设置为 1 是正确的,这就是我目前所拥有的,因为我还在该特定属性上调用zval_ptr_dtor
将其引用计数从 2 减少到 1。ZE将照顾好剩下的。
@hakre's question made me think.
The explanation is the following: when the ZE destroys the object, it also destroys (
zval_ptr_dtor
) each property of the object. So it is right to have a refcount of 1 after the destructor was called, which is what I have currently, since I also callzval_ptr_dtor
on that specific property decreasing its refcount from 2 to 1.The ZE will take care of the rest.