以下是我创建的测试函数(适用于PHP 7.1)。
PHP_FUNCTION(tsc_test3)
{
zend_string *cnA;
zend_class_entry *ceA;
// $ret = new ClsA();
cnA = zend_string_init("ClsA", 4, 0);
ceA = zend_fetch_class(cnA, ZEND_FETCH_CLASS_DEFAULT);
zend_string_release(cnA);
object_init_ex(return_value, ceA);
// $ret->propA = $ret;
zval objA;
ZVAL_COPY(&objA, return_value);
zend_update_property(ceA, return_value, "propA", 5, &objA);
zval_ptr_dtor(&objA);
return;
}
如注释中所建议的,它返回一个循环对象ClsA
。 以下是该函数的测试 PHP 程序。
<?php
class ClsA {
public $propA = 1;
}
$x = tsc_test3();
echo "DUMP1 ----n";
var_dump($x);
for ($i = 0; $i < 10; $i++) {
echo "Memory usage: ". memory_get_usage(). "n";
$x = tsc_test3();
}
echo "DUMP2 ----n";
var_dump($x);
$x->propA = null;
echo "DUMP3 ----n";
var_dump($x);
这是 PHP 代码的输出。
转储1 ---- object(ClsA)#1 (1) { ["propA"]=>*递归* } 内存使用情况:351336 内存使用情况:351392 内存使用情况:351448 内存使用量:351504 内存使用量:351560 内存使用量:351616 内存使用量:351672 内存使用量:351728 内存使用情况:351784 内存使用量:351840 转储2 ---- object(clsA)#11 (1) { ["propA"]=>*递归* } 转储3 ---- object(clsA)#11 (1) { ["propA"]=>NULL }
var_dump()
结果看起来不错,但内存使用量不断增加。
当我使用ZVAL_COPY_VALUE
而不是ZVAL_COPY
时,内存使用量不会增加,但它会在 DUMP3 中产生奇怪的输出。
转储3 ---- *递归*
可能是函数返回损坏的对象。
谁能告诉我扩展功能出了什么问题?
编辑1:发布问题后,我注意到memory_get_usage(true)
没有增加。这是我犯的错误吗?
编辑2:以下PHP程序(纯PHP,无扩展)显示内存使用量增加。这是一个PHP错误还是我误解了什么?我正在使用 PHP 7.1.28。
<?php
class ClsA {
public $propA = 1;
}
for ($i = 0; $i < 10; $i++) {
echo "Memory usage: ". memory_get_usage(). "n";
$x = new ClsA();
$x->propA = $x;
}
这是因为PHP垃圾回收器并不总是在您将引用($x
)分配给另一个对象时回收对象(ClsA
实例)使用的内存。PHP 完全使用 ref 计数和垃圾回收。
如果在每个循环上强制进行垃圾回收,您将看到内存占用量将保持不变:
<?php
class ClsA {
public $propA = 1;
}
for ($i = 0; $i < 10; $i++) {
gc_collect_cycles();
echo "Memory usage: ". memory_get_usage(). "n";
$x = new ClsA();
$x->propA = $x;
}
输出:
$ php test.php
Memory usage: 396296 <-- before the first ClsA allocation
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
Memory usage: 396384
更多(技术)信息在这里 : https://www.php.net/manual/en/features.gc.collecting-cycles.php