我正在将php扩展升级到php 7,我想删除使用zend_register_resource
在常规列表中注册的资源,之后我使用zend_list_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));
...
}
最初在PHP 5中,使用rsrc
删除zend_hash_index_del( &EG( regular_list ), Z_RESVAL_P( rsrc))
,因此如果此函数被调用两次,zend_parse_parameter
将返回FAILURE
,因为资源已从常规中删除列表并不存在。
在PHP7中,zend_list_close
调用zend_resource_dtor
(rsrc refcount为2
(为什么会增加?注册资源后为1))并清除rsrc
的所有内存忍住了。但是,当我们这样称呼它两次时会发生这种乐趣:
myFunc_cleanAndExit($var-rsrc);
myFunc_cleanAndExit($var-rsrc);
第二次zend_parse_parameter没有返回FAILURE(导致资源没有从常规列表中删除),并且rsrc
的refcount在解析后递增到3
, type为-1且ptr为NULL(在第一次调用中在zend_resource_dtor中分配)。当我在PHP脚本中调用get_resources()
时,我得到rsrc
及其ID UNKOWN
,其中PHP5 rsrc
变为NULL
。以下是我的问题:
1-什么时候从常规列表中删除资源? (如果我使用zend_hash_index_del
从常规列表中手动删除它,它会在zend_alloc中中断)
2-关闭一次后资源UNKOWN
的资源是否可用?不吃掉记忆?如果没有,我该怎么办才能把它作为NULL?
3-当我注册资源并检查其引用计数时,它是1,但是当我调用结束函数时,zend_parse_parameter
后引用计数增加,为什么?
由于
示例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'
答案 0 :(得分:3)
简短的回答是资源会在请求关闭时被删除,特别是在zend_hash_graceful_reverse_destroy
中。您还应该检查zend_fetch_resource
的返回值,因为它将为被破坏的资源返回NULL(并发出警告)。
我认为你所描述的一切都是正常的,包括zend_parse_parameters
成功解析以前被破坏的资源。以下程序表现出完全相同的行为:
<?php
$r = popen('ls', 'r');
echo fgets($r);
pclose($r);
var_dump(get_resources());
pclose($r);
您的资源的引用计数为2,因为SEND_VAR
操作码(即将一个参数传递给一个函数)将ZVAL_COPY
传递给arglist,这会增加引用计数。 (稍后在zend_vm_stack_free_args
中解析了。)
关于内存使用情况,我不担心资源占用内存。我们已经知道它在RSHUTDOWN
清理时没有泄漏。即使您要从哈希中手动删除项目,我也不认为底层内存会立即被释放。