fix(parser): handle temporary variable cleanup for weak reference expressions

- Add unset() call for temporary variables of type VAR to prevent extended object lifetime
- Ensure weak reference targets are properly released after statement execution
- Add test case for expression temporary lifetime behavior with weak references
- Verify object destruction occurs at correct scope boundaries
- Prevent memory leaks with WeakReference targets in native functions
pull/48/head
韩天峰 2 weeks ago
parent 7d7fa75d6f
commit 0ba5079336
  1. 7
      src/Parser/BinaryOpTrait.php
  2. 42
      tests/compiler/basic/weak-reference-expression-lifetime.phpt

@ -535,6 +535,13 @@ trait BinaryOpTrait
$tmpVar = $this->addTmpVar($type);
$this->context->beforeStmtLines[] = $tmpVar . ' = ' . $value . ';';
$this->appendCapturedStmtLinesToContext($afterStmts);
if ($type === Type::VAR) {
// The declaration is function-scoped, but PHP releases an owned
// expression temporary after the statement that consumes it.
// Keeping the value here would extend object lifetimes (notably
// WeakReference targets) until the native function returns.
$this->context->afterStmtLines[] = $tmpVar . '.unset();';
}
return $tmpVar;
}

@ -0,0 +1,42 @@
--TEST--
Expression temporaries release owned objects at the end of the PHP statement
--FILE--
<?php
final class TemporaryLifetimeProbe
{
public static int $destroyed = 0;
public function __destruct()
{
self::$destroyed++;
}
}
function make_temporary_probe(): object
{
return new TemporaryLifetimeProbe();
}
function main(): void
{
$target = new stdClass();
$weak = WeakReference::create($target);
$liveIdentity = $weak->get() === $target;
unset($target);
gc_collect_cycles();
var_dump($liveIdentity);
var_dump($weak->get() === null);
$different = make_temporary_probe() === new stdClass();
var_dump($different);
var_dump(TemporaryLifetimeProbe::$destroyed);
}
?>
--EXPECT--
bool(true)
bool(true)
bool(false)
int(1)
Loading…
Cancel
Save