5

今日までPHPでSegFaultを見たことがありませんが、それは可能だと思われます。最初はmysqlドライバーだと思っていましたが、私のコードであることがわかりました;)。

私は約2日間コードのデバッグに費やし、最終的にその原因を突き止めました(したがって、これに遭遇する将来のPHPプログラマーの皆さん、どういたしまして!)

簡単に言えば、あなたが歩いている間、あなたが歩いているのと同じ配列で行うことはできません。unset()array_walk()

目的は、$out配列に存在しない$this->votesからすべての要素を削除することです($ this->votesのキーが$out内の要素の1つのidプロパティと一致する場合)。

私が抱えていた問題は、コードが正常に実行される時間の約半分であり、残りの半分は、apacheログのセグメンテーション違反でクラッシュしました(このエラーに気付くまでしばらく時間がかかったため、デバッグがかなり困難になりました)。

そして、ええ、それはそもそもかなりよく考えられていないコードです...。

    array_walk($this->votes, function(&$o, $key) use($that, $out) {
        $found = array_filter($out, function($p) use($key) {
            return $p['id'] == $key;
        });

        if(count($found) == 0) {
            unset($this->votes[$key]); //very very bad!!!!
        }
    });
4

1 に答える 1

3

私が理解しているように、最終的に発生するのは、配列の長さをunset()台無しにすることです。ウォーク全体を通して配列が同じ長さを維持することを期待するイテレータを使用します。独自の関数()を作成した場合、未定義のインデックス通知がスローされます。しかし、私たちが使用しているので、実際には、データがある場合とない場合があるメモリ内の場所を調べようとします。これにより、関数が予測不能になる可能性があります(コードが正常に実行される場合もあれば、セグメンテーション違反が発生する場合もあります)。$this->votearray_walk$this->votesarray_walkfor ($i = 0; $i < count($this->votes); $i++array_walk

したがって、それを行う正しい方法は次のようになります

    $tmpVotes = array();
    array_walk($this->votes, function(&$o, $key) use($that, $out, $tmpVotes) {
        $found = array_filter($out, function($p) use($key, $that, $tmpVotes) {
            return $p['id'] == $key;
        });

        if(count($found) > 0) {
            $tpmVotes[$key] = $o;
        }
    });

    $this->votes = $tmpVotes;

PHPマニュアルから:

配列の値のみが変更される可能性があります。その構造を変更することはできません。つまり、プログラマーは要素を追加、設定解除、または並べ替えることはできません。コールバックがこの要件を尊重しない場合、この関数の動作は定義されておらず、予測できません。

誰かがここで何が起こっているのかを説明するより良い方法を持っているなら、投稿してください!

于 2013-02-07T21:15:41.393 に答える