PHP segfault, когда оператор распространения применяется к объекту


ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ:: Посмотрите на ответ


Хорошо, учитывая этот фрагмент кода

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. Я мог бы в некотором смысле создать новый массив, который "отменяет" аргумент $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 в последней строке обратного вызова - это то, что segfaults, когда и только когда формат создается if, когда он проходит через else, работает нормально.

Я способ, которым я создаю свой формат, не разрешен? is действительно создает допустимый формат для, насколько я знаю, "'count(%s.%s)", еще несколько тестов показывают мне, что когда я изменяю назначение $format в if на $format = '%s.%s' Я все еще получаю segfault.

Самое странное, что вчера, когда я делал укол, я получил все... При вводе этого php, похоже, решил, что теперь этот код подходит.. То, что я пытался сказать, что вчера это не произошло, пока в zf3 new PDO не было называется...

Я действительно не знаю, где искать...

Author: Chris Kruining, 2017-11-09

1 answers

Хорошо, короче говоря, это не имело никакого отношения к регулярным выражениям или сдвигам массивов. Оказывается, что оператор ...(spread), применяемый к объекту, у которого есть ArrayAccess, IteratorAggregate и т. Д., Все, что заставляет этот объект работать как массив, Случайным образом, кажется, сегментируется при вызове с оператором ....


Т.е., учитывая эту сигнатуру класса, мы способны обрабатывать этот класс, как если бы он был массивом (здесь нет деталей реализации, чтобы сэкономить место в объяснение)

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 содержит добавленные элементы дерева. если бы $foo было array, мы могли бы сделать function(...$foo), что привело бы к вызову функции function('one', 'two', 'three'). верно? хорошо, тогда, когда я сделал это в своем коде с моим классом Collection (в некотором смысле, с моим классом Foo), он будет сегментирован (не всегда, только с определенными экземплярами, и нет; ключи не были определены, я проверил это, и, как и с массивом, он выдаст ошибку "не удается распаковать массив с ключами").


Я все еще понятия не имею, почему это так просто, что мой обходной путь состоит в том, чтобы привести мой Collection к array. Я также не знаю, является ли это известной ошибкой в PHP и как ее действительно искать.


TL;DR::при использовании оператора ... для распаковки убедитесь, что то, что вы пытаетесь распаковать, является array ;)

 0
Author: Chris Kruining, 2017-11-10 14:52:24