Method call may leak if releasing EG(This) triggers GC

未关闭
#13,687 5 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
38/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
c, php
领域
backend

调研方向

使用 test.php 示例重现内存泄漏,然后检查 zend_vm_def.h 中 2866 行和 4019 行附近链接的调用点,以及来自 Zend/zend_objects.c 的泄漏报告。确认修复不会让返回的循环对象继续处于未回收状态,并确认该示例不再报告内存泄漏。

由索引模型根据 Issue 内容生成。

描述

Bug Category: GC Waiting on Author
Description

Method calls may cause their return value to leak if releasing EG(This) triggers GC.

The following code:

<?php

class A {
    public $cycle;
    public function __construct() { $this->cycle = $this; }
}
class B {
    public function get() {
        return new A();
    }
}

$c = new B();
$objs = [];

while (gc_status()['roots']+2 < gc_status()['threshold']) {
    $obj = new stdClass;
    $objs[] = $obj;
}

var_dump($c->get());

Resulted in a memory leak:

Script:  'test.php'
Zend/zend_objects.c(189) :  Freeing 0x00007ffff7a5c840 (56 bytes), script=test.php
=== Total 1 memory leaks detected ===

Here is what is happening:

  • After returning from get(), $c is released, which triggers GC
    • A is removed from buffer, and is not collected because it's referenced by the call stack
  • After returning from var_dump(), zend_vm_stack_free_args() releases A with zval_ptr_dtor_nogc(), so A is not added to the GC buffer
  • At this point nothing references A but itself, and A is not in the GC buffer, so it leaks

I'm not sure how to fix this appart from switching to zval_ptr_dtor().

PHP Version

master

Operating System

No response

主要语言
C
星标
40.4k
派生
8.2k
平均合并
2 天 15 小时
30 天内合并 PR
103

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

php/php-src 的其他 Issue

查看 php/php-src 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。