如何诊断PHP-Code-Coverage分段和zend_mm_heap损坏错误

11

我一直在我的Ubuntu机器上快乐地编码。这是一台配置良好的机器,有足够的RAM。我正在编写和运行单元测试时,处理着4个新类。在某个时刻,我注意到,尽管单元测试完成得很好,但代码覆盖率并没有。

在“生成代码覆盖率报告...等”消息之后,我会得到一个消息,指出zend_mm_heap已损坏。我尝试了一些修复方法,包括:在我的php.ini (apache2和cli都设置为output_buffering = On),以及从我的代码中删除对unset()的调用。(我在SO上读到这些修复可能是必需的)

现在,不管我做什么,我似乎都在zend_mm... 错误和段错误(core dump)错误之间交替。我注释掉测试,直到我缩小到认为是引起问题的测试,并在那里进行一些更改,直到我获得干净的运行。然后我会取消注释所有测试,只发现故障仍然发生。

有什么想法吗?我可以使用哪些工具或方法来收集更多信息?

我正在使用PHP_CodeCoverage 1.2.6、PHP 5.3.10-1ubuntu3.5、PHPUnit 3.7.9。

编辑:

顺便说一句,我找不到任何核心转储文件。我已经从我的物理磁盘的根目录开始搜索,但没有找到。我已经阅读了core的手册条目,包括不创建文件的核心转储的可能原因,但我不认为这些情况适用。

3个回答

25

我最近遇到同样的问题。这似乎是PHP垃圾回收的问题。在phpunit运行期间禁用垃圾回收可以解决我的问题。

补充:

zend.enable_gc=0 

您可以通过编辑 php.ini 文件或者使用命令行来进行设置:

phpunit -d zend.enable_gc=0

2
关于获取更多信息,您可以尝试使用gdb回溯。在gdb中,运行gdb php,然后输入run /usr/bin/phpunit。当phpunit崩溃时,请输入bt。更多信息请参见http://www.ofb.net/gnu/gdb/gdb_42.html。 - Blake Fitzgerald
Blake,你太棒了。如果我能给你颁发奖章,我一定会的! - DatsunBing
哇!它为我节省了很多时间! - Morgan Cheng
1
禁用gc是否安全,能确保内存安全吗? - ozahorulia
@Hast 很可能不是。我猜这只是在开发环境中被视为临时解决方案,因此内存安全性并不是那么重要的问题。 - fquffio

3

有时候,运行 PhpUnit 代码覆盖率时很难理解 Segmentation fault 错误。我在 PHP 7.0.5 上使用了两个版本的 PhpUnit 都遇到了分段错误。

最终,在追踪问题时,我发现像这样的问题导致了分段错误。

$x = doSomething(doSomethingElse());

并将内部函数提取到变量中,如下所示:

$y = doSomethingElse();
$x = doSomething($y);

已解决问题。 当然,以上只是简化的代码,但您应该明白,有时您的代码没有真正的错误,但您应该修改它以使PhpUnit与代码覆盖率一起使用。


我最近也遇到了完全相同的问题。你有任何线索为什么会发生这种情况吗?我的意思是,这显然是100%有效的代码。它怎么可能失败呢? - Karim Geiger
我的情况类似:将以下代码进行更改: DB::raw('(' . $this->getCommentCountQuery()->toSql() . ') AS fl_comments_count')更改为: DB::raw("($comment_count_query) AS fl_comments_count")问题已解决。 - ImLeo
这是另一个例子,从 return SnappyPdf::loadHTML($this->renderHTML())... $html = $this->renderHTML(); return SnappyPdf::loadHTML($html)... - ImLeo

1
我曾经遇到同样的问题,并尝试使用zend.enable_gc=0,但是phpunit会因为内存不足而停止运行。为了解决这个问题,我基本上修改了我的覆盖白名单,让它更加细化。所以,在phpunit.xml中,我之前有这样的设置:
<filter>
    <whitelist>
        <directory suffix=".php">../application/src</directory>
    </whitelist>
</filter>

我把它改成了这样:


<filter>
    <whitelist>
        <directory suffix=".php">../application/src/module1</directory>
        <directory suffix=".php">../application/src/module2</directory>
        <directory suffix=".php">../application/src/module3</directory>
        <exclude>
            <directory>../application/src/module1/views</directory>
        </exclude>

    </whitelist>
</filter>

所以尽量限制过滤器仅包含实际重要的文件。这仍然是一个错误,但现在我认为限制考虑覆盖率计算的文件数量将有助于防止这些问题的发生。

1
这就是对我来说的解决方案。 - pedromanoel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接