PHP7如何从常规列表中删除资源?
我正在将一个php扩展升级到PHP7,我想删除一个使用PHP7如何从常规列表中删除资源?,php,php-extension,php-7,php-internals,Php,Php Extension,Php 7,Php Internals,我正在将一个php扩展升级到PHP7,我想删除一个使用zend\u register\u resource在常规列表中注册的资源,然后我将使用zend\u list\u close关闭该资源。关闭函数如下所示: PHP_FUNCTION(myFunc_cleanAndExit) { zval* rsrc = NULL; ... int res = zend_parse_parameters(ZEND_NUM_ARGS() , "r", &rs
zend\u register\u resource
在常规列表中注册的资源,然后我将使用zend\u list\u close
关闭该资源。关闭函数如下所示:
PHP_FUNCTION(myFunc_cleanAndExit)
{
zval* rsrc = NULL;
...
int res = zend_parse_parameters(ZEND_NUM_ARGS() , "r", &rsrc );
if (res == FAILURE)
{
//handle it
}
...
zend_fetch_resource(Z_RES_P(rsrc), ./other args/..)
...
zend_list_close(Z_RES_P(rsrc));
...
}
myFunc_cleanAndExit($var-rsrc);
myFunc_cleanAndExit($var-rsrc);
最初在PHP5中,rsrc
是使用zend\u hash\u index\u del(&EG(regular\u list),Z\u RESVAL\u p(rsrc))
删除的,因此如果调用两次此函数,zend\u parse\u参数
返回失败,因为资源已从常规列表中删除且不存在
在PHP7中,zend_list_close
调用zend_resource_dtor
(rsrc refcount是2
(为什么是递增的?注册资源后是1)),并清除rsrc
占用的所有内存。但是,有趣的是,当我们两次这样称呼它时:
PHP_FUNCTION(myFunc_cleanAndExit)
{
zval* rsrc = NULL;
...
int res = zend_parse_parameters(ZEND_NUM_ARGS() , "r", &rsrc );
if (res == FAILURE)
{
//handle it
}
...
zend_fetch_resource(Z_RES_P(rsrc), ./other args/..)
...
zend_list_close(Z_RES_P(rsrc));
...
}
myFunc_cleanAndExit($var-rsrc);
myFunc_cleanAndExit($var-rsrc);
第二次zend_parse_参数不返回FAILURE(因为资源尚未从常规列表中删除),并且解析后rsrc
的refcount增加到3
,类型为-1,ptr为NULL(在第一次调用中在zend_resource_dtor中分配)。在PHP脚本中调用get_resources()
时,我会得到带有id和类型unknown
的rsrc
,它在PHP5rsrc
中变为NULL
。以下是我的问题:
1-何时从常规列表中删除资源?(如果我使用zend\u hash\u index\u del
手动将其从常规列表中删除,它将在zend\u alloc中中断)
2-关闭一次后,是否可以使用类型为未知的激活资源?不会耗尽记忆吗?如果不是,我应该如何将其设置为空
3-当我注册资源并检查其refcount时,它是1,但当我调用closing函数时,在zend\u parse\u参数之后,refcount会增加,为什么
谢谢
PHP脚本示例:
<?php
$var_rsrc = myFunc_startUp();
var_dump($var_rsrc); // resource(2) of type 'MyFunc'
myFunc_cleanAndExit($var_rsrc);
var_dump($var_rsrc); // resource(2) of type 'UNKOWN' (originally this was NULL)
myFunc_cleanAndExit($var_rsrc);
var_dump($var_rsrc); // resource(2) of type 'UNKOWN'
简单的回答是,资源在请求关闭时被删除,特别是在zend\u hash\u优雅\u reverse\u destroy
中。您还应该检查zend_fetch_resource
的返回值,因为它将为已破坏的资源返回NULL(并发出警告)
我认为您所描述的一切都是正常的,包括zend_parse_参数
成功解析以前被破坏的资源。下面的程序显示了完全相同的行为:
<?php
$r = popen('ls', 'r');
echo fgets($r);
pclose($r);
var_dump(get_resources());
pclose($r);
谢谢@adsr,在PHP5 zend_parse_中,参数返回失败,因为该参数实际上不存在并且已从列表中删除,为什么我们不能在PHP7中有相同的行为?@Genjutsu感谢接受我的回答。我有点怀疑这种改变是故意的。这更有可能是堆栈与堆分配ZVAL的副作用。作为一个边缘案例,您可以争辩说,有人可能想要重新实例化他们以前破坏的资源,在这种情况下,zpp成功是可取的。将其与PHP5的背部兼容性进行权衡,这是一个难题。