【问题标题】:PHPUnit Segmentation faultPHPUnit 分段错误
【发布时间】:2011-09-14 16:19:05
【问题描述】:

当我的开发盒 (Linux Mint) 上的 PHPUnit 测试正常失败时,它会在我的持续集成盒 (Centos) 上导致“分段错误”。两台机器都运行相同版本的 PHPUnit。我的开发箱运行 PHP 5.3.2-1ubuntu4.9,CI 是 PHP 5.2.17。不过,我宁愿把升级 PHP 作为最后的手段。

根据这个线程:PHPUnit gets segmentation fault 我试过停用/重新安装 Xdebug。我没有安装 inclue.so。

在 CI 框上,我目前只有两个处于活动状态的扩展:来自 php-xml 的 dom(phpunit 需要)和 memcache(我的框架需要),所有其他的都已关闭。

【问题讨论】:

  • 请说明您如何调用 PHPUnit。你试过进程隔离吗?
  • @hakre - 是的,我已经尝试过进程隔离,但由于我的框架没有正确实例化,我得到的只是错误。我只是从命令行调用它:phpunit quiz_service_Test.php
  • 它是每次还是偶尔崩溃?另外:您根本不使用任何 5.3 功能(所以目标是创建兼容 5.2 的软件?- 就像@powtac 所说,更多内存可能总是有帮助:)
  • @powtac 我在 php.ini 中的 memory_limit 已设置为 300M,我只运行了一个有问题的测试。还有其他地方我应该寻找内存设置吗?
  • @hakre 只有一些测试用例有这个问题。特别是它试图使用创建失败的套接字的地方。

标签: php segmentation-fault phpunit


【解决方案1】:

当您遇到段错误时,请将您的 PHP 升级到最新版本。不仅是您的包管理器中的最新版本,还有 php.net 上的最新版本。如果它仍然存在段错误,那么您确定问题尚未在 PHP 本身中得到解决。不要费心试图摆脱旧版本 PHP 中的段错误,因为它可能已经在新版本中修复了。

下一步是定位问题:使您的测试越来越小,直到您无法删除任何东西(但它仍然存在段错误)。如果你有,将测试移动到一个独立的段错误的 php 脚本中。现在您在 PHP 错误跟踪器中为您的错误提供了一个测试脚本。

【讨论】:

    【解决方案2】:

    在 cweiske 建议的旁边,如果升级 PHP 不是您的选择,并且您在定位 segfault 的来源时遇到问题,您可以使用调试器来查找更多信息。

    您可以通过这种方式启动 gdb 来调试 PHPUnit 会话:

    gdb --args php /usr/bin/phpunit quiz_service_Test.php
    

    然后输入r 以运行程序和/或首先设置环境变量。

    set env MALLOC_CHECK_=3
    r
    

    您也可以考虑在系统上安装 PHP 的调试符号以获得更好的调试结果。 gdb 会在启动时为您检查这一点,并通知您如何执行此操作。

    【讨论】:

    • 谢谢,这帮助我缩小了范围。我们从服务器返回的数据对于 pcre 来说太大了。
    • 好的。您可以限制它,以便 preg_... 不会出现段错误,但也不会完全执行(如果失败,通常返回 NULL)。 See the ini settings for pcre.
    【解决方案3】:

    我遇到了 PHPUnit segfaulting 的问题,并且无法找到答案,因此希望这对以后遇到相同问题的人有所帮助。

    PHPUnit 出现了段错误,但只有:

    • 如果出现错误(或多个错误)
    • 在所有测试运行之后但在打印错误之前

    过了一会儿,我意识到这是由于使用数据提供者的测试失败造成的,特别是对于传递具有大量递归引用的对象的数据提供者。钟声终于响起,我进行了一些挖掘:问题是,当您使用数据提供程序并且测试失败时,PHPUnit 会尝试为失败描述创建所提供参数的字符串表示形式,以告诉您失败的原因,但这当其中一个参数具有无限递归时是有问题的。事实上,PHPUnit 在PHPUnit_Framework_TestCase::dataToString()(大约第 1612 行)中所做的就是打印出数据提供者使用print_r 提供的所有参数,这会在 PHP 尝试创建无限递归对象的字符串表示时导致段错误。

    我的解决方案是:

    1. 为我的所有测试类使用一个基类(幸运的是我已经这样做了)
    2. 在我的测试基类中重写dataToString(),以检查数据数组中的这些类型的对象(在我的情况下这是可能的,因为我知道这些对象的样子)。如果对象存在,我会返回一些特殊值,如果不存在,则将其传递给父方法。

    【讨论】:

    • 这实际上帮助了很多。一种更好的方法是在测试本身中创建数据结构,并在 dataprovider 中仅创建普通数据(这对我有用)
    【解决方案4】:

    我遇到了同样的问题。我将 PHPUnit 升级到 4.1 版本(以运行测试),它能够向我显示对象,正如 Isaac 所指出的那样。

    因此,如果您遇到同样的问题,请升级到 PHPUnit >= 4.1,您将能够看到错误,而不是收到“分段错误”消息。

    【讨论】:

      【解决方案5】:

      在运行具有代码覆盖率的 PHPUnit 时,我不断收到 Segmentation fault: 11。在对分段错误进行堆栈跟踪后,我发现导致分段错误错误的原因如下:

      Program received signal SIGSEGV, Segmentation fault.
      0x0000000100b8421a in xdebug_path_info_get_path_for_level () from /usr/lib/php/extensions/no-debug-non-zts-20121212/xdebug.so
      

      我用我拥有的 PHP 版本(对我来说是 5.5)将相应下载包的子文件夹 Komodo Remote Debugging Package 中的最新版本替换为上面路径中的当前xdebug.so,一切正常。

      【讨论】:

        【解决方案6】:

        以下解决了我的类似问题(当gdb 回溯的输出包括libcurl.solibcrypto.so 时):

        禁用/etc/php.d/pgsql.ini:

        ; Enable pgsql extension module
        ; extension=pgsql.so
        

        编辑 /etc/php.d/curl.ini 以确保在 curl 之前包含 pgsql.so

        ; Enable curl extension module
        extension=pgsql.so
        extension=curl.so
        curl.cainfo=/home/statcounter/include/config/cacert.pem
        

        【讨论】:

          【解决方案7】:

          我遇到了类似的问题,并且在

          中禁用了垃圾收集器

          PHPStorm => 编辑配置 => 解释器选项:-d zend.enable_gc=0

          或者,如果您是从命令行运行测试,您可以尝试添加:

          -d zend.enable_gc=0

          【讨论】:

            【解决方案8】:

            除了https://stackoverflow.com/a/38789046/246790对我帮助很大:

            可以使用PHP函数gc_disable();

            我已经把它和ini_set('memory_limit', -1);一起放在了我的PHPUnit引导代码中

            【讨论】:

            • 这似乎更像是一种“暂时掩盖”问题的手段,而不是真正解决问题。即,您正在关闭捕获循环引用的机制,然后删除阻止 PHP 吞噬所有 RAM 的内存限制器,这可能会破坏其他事物的稳定性,例如操作系统。
            【解决方案9】:

            这与代码而不是扩展有关。就我而言,我有这两个文件

            1. 测试用例
            2. 示例测试

            Test Case 中有一个名为createApplication 的方法。把它留空。
            Example Test 中,您可以创建方法并填写 $this->assertTrue(true)

            以上是基本设置,希望您可以根据需要扩展要求。

            【讨论】:

              【解决方案10】:

              我遇到了同样的问题并且可以确定,我试图编写一个未定义的类变量:

              导致分段错误的我的类(它是一个 cakePHP 类):

              class MyClass extends AppModel {
              
                protected $classVariableOne;
              
                public function __construct($id = false, $table = null, $ds = null) {
                  parent::__construct($id, $table, $ds);
              
                  $this->classVariableOne =& ClassRegistry::init('ClassVariableOne');
              
                  // This line caused the segmentation fault as the variable doesn't exists
                  $this->classVariableTwo =& ClassRegistry::init('ClassVariableTwo');
              
                }
              }
              

              我通过添加第二个变量来修复它:

              class MyClass extends AppModel {
              
                protected $classVariableOne;
                protected $classVariableTwo; // Added this line
              
                public function __construct($id = false, $table = null, $ds = null) {
                  parent::__construct($id, $table, $ds);
              
                  $this->classVariableOne =& ClassRegistry::init('ClassVariableOne');
                  $this->classVariableTwo =& ClassRegistry::init('ClassVariableTwo');
              
                }
              }
              

              【讨论】:

                【解决方案11】:

                无限递归通常是导致我们这个问题的原因。在 phpunit 下运行代码时,无限递归的症状似乎与在其他环境中运行时不同。

                【讨论】:

                  【解决方案12】:

                  如果有人在 Laravel 中遇到与 PHPunit 相关的问题

                  花了一段时间才弄清楚问题出在哪里。我正在检查我当前的代码和以前的版本之间的差异,并通过一些试验和错误终于到达那里。

                  我有两个不同的模型,它们都通过 protected $with 覆盖相互包含。

                  这一定是导致了某种 phpunit 无法处理的循环。

                  希望有人觉得这很有用。

                  【讨论】:

                    【解决方案13】:

                    如果你有一个对象的属性指向同一个对象,或者其他类型的指针循环,你会在运行时看到这个消息

                    serialize($object);
                    

                    如果你是 Laravel 用户,并且你正在处理模型。如果您认为,您将永远不会遇到这个问题,因为您在模型上使用$hidden 属性避免了指针循环,请注意,$hidden 属性不会影响serialize,它只会影响转换为@987654325 @ 和array

                    当我将模型保存到Mailable 对象的属性中时,我遇到了这个问题。

                    固定
                    $this->model->refresh(); 
                    

                    __construct 方法中,就在整个对象被序列化之前。

                    【讨论】:

                      猜你喜欢
                      • 2012-10-27
                      • 2023-03-14
                      • 1970-01-01
                      • 2016-08-06
                      • 2014-09-30
                      • 2011-04-03
                      • 2010-12-04
                      • 2011-11-29
                      相关资源
                      最近更新 更多