对象的销毁

3.4.2.6 对象的销毁

object与string、array等类型不同,它是个符合类型,所以它的销毁过程更加复杂,赋值、函数调用结束或主动unset等操作中如果发现object引用计数为0则将触发销毁动作。

//情况1
$obj1 = new my_function();

$obj1 = 123; //此时将断开对zend_object的引用,如果refcount=0则销毁

//情况2
function xxxx(){
    $obj1 = new my_function();
    ...
    return null; //清理局部变量时如果发现$obj1引用为0则销毁
}

//情况3
$obj1 = new my_function();
//整个脚本结束,清理全局变量时

//情况4
$obj1 = new my_function();
unset($obj1);

上面这几个都是比较常见的会进行变量销毁的情况,销毁一个对象由zend_objects_store_del()完成,销毁的过程主要是清理成员属性、从EG(objects_store).object_buckets中删除、释放zend_object内存等等。

//zend_objects_API.c
ZEND_API void zend_objects_store_del(zend_object *object)
{
    //这个函数if嵌套写的很挫...
    ...
    if (GC_REFCOUNT(object) > 0) {
        GC_REFCOUNT(object)--;
        return;
    }
    ...

    //调用dtor_obj,默认zend_objects_destroy_object()
    //接着调用free_obj,默认zend_object_std_dtor()
    object->handlers->dtor_obj(object);
    object->handlers->free_obj(object);
    ...
    ptr = ((char*)object) - object->handlers->offset;
    efree(ptr);
}

另外,在减少refcount时如果发现object的引用计数大于0那么并不是什么都不做了,还记得2.1.3.4介绍的垃圾回收吗?PHP变量类型有的会因为循环引用导致正常的gc无法生效,这种类型的变量就有可能成为垃圾,所以会对这些类型的zval.u1.type_flag打上IS_TYPE_COLLECTABLE标签,然后在减少引用时即使refcount大于0也会启动垃圾检查,目前只有object、array两种类型会使用这种机制。

联系我们

邮箱 626512443@qq.com
电话 18611320371(微信)
QQ群 235681453

Copyright © 2015-2024

备案号:京ICP备15003423号-3