PHP 将扩展运算符应用于对象时出现段错误

PHP segfault when spread operator is applied to object

最终编辑 :: 查看答案


好的,给定这段代码

private function select(string $key, string ...$keys): Model
{
    \array_unshift($keys, $key);

    foreach($keys as &$key)
    {
        $key = \preg_replace_callback('/([a-zA-Z]+)\((.*)\)/', function($match){
        return \sprintf('%s(%s)', $match[1], $this->primaryFields()->keys()->first());
    }, $key);
}

在这种情况下,写入密钥的行出现段错误,起初我认为这是因为Prce发生了一些奇怪的事情。但是,当我用字符串文字设置它时,会发生同样的情况。最后我通过注释掉 array_unshift 解决了这个问题。从某种意义上说,我可以创建一个新数组,其中 'unshifts' $key 参数,但我认为这不是必需的,有没有人知道这是 PHP 怪癖,还是我是不是误会了什么?

顺便说一句,我是 运行 php7.1 作为 fpm


编辑::

好吧,我正在写我正在开发的整个故事,但我似乎已经查明了原因,它是一个 sprintf 特别是这个块

$keys = \array_map(function($key){
    $matches = Regex::match('/([a-zA-Z]+)\((.*)\)/', $key);

    $string = \key_exists(2, $matches)
        ? $matches[2]
        : $key;

    if(\count($matches) > 0)
    {
        $format = \sprintf('%s(%%s.`%%s`)', $matches[1]);
    }
    else
    {
        $format = $string === '*'
            ? '%s.%s'
            : '%s.`%s`';
    }

    return \sprintf($format, $this->owner->getTarget(), $string);
}, $this->keys);

回调最后一行的 sprintf 是什么段错误,当且仅当格式由 if 创建时,当它通过 else 时工作正常。

我创建格式的方式不被允许?据我所知,它确实为“'count(%s.%s)”创建了一个有效格式,更多测试表明,当我将 if 中的 $format 赋值更改为 $format = '%s.%s' 我仍然遇到段错误。

最奇怪的是,昨天当我进行精确定位时,我得到了所有...虽然输入此 php 似乎已经确定此代码现在是正确的..我正在尝试的可以说昨天它没有出现段错误,直到在 zf3 中 new PDO 被调用...

我真的不知道去哪里看...

好吧,长话短说,它与正则表达式或数组移位无关。事实证明,应用于具有 ArrayAccess、IteratorAggregate 等对象的 ...(spread) 运算符,使该对象作为数组工作的所有内容,在使用 ... 运算符调用时似乎随机出现段错误。


即鉴于此 class 签名,我们能够像处理数组一样处理此 class(此处没有实现细节以在解释中保存 space)

class Foo implements \ArrayAccess, \IteratorAggregate
{
    public function getIterator()

    public function offsetExists($offset)
    public function offsetGet($offset)
    public function offsetSet($offset, $value)
    public function offsetUnset($offset)
}

$foo = new Foo;
$foo[] = 'one';
$foo[] = 'two';
$foo[] = 'three';

好吧,让我们同意 $foo 包含树添加的项目。如果 $fooarray,我们可以做 function(...$foo),这将导致函数调用 function('one', 'two', 'three')。正确的?好吧,当我在我的代码中用我的 Collection class(我的 Foo 在某种意义上)这样做时,它会出现段错误(不总是,只是在某些情况下,没有;有没有定义键,我测试了它,以及一个数组它会给出一个错误 "can't unpack array with keys").


我仍然不知道为什么会出现段错误,只是我的解决方法是将我的 Collection 转换为 array。我也不知道这是否是 PHP 上的已知错误,也不知道如何真正搜索它。


TL;DR :: 使用 ... 运算符解包时,请确保您尝试解包的内容是 array ;)