Archive for the ‘Modulecategory

PHP tõrge Pesitsustase liiga sügav rekursiivne sõltuvus

12. märts, 2010

Ma installitud PHP 5.2 ühel minu testimisarvutid täna ja paar bitti koodi, mis varem töötas trahvi versioon 5.1.6 viskas uue versiooni surmaga lõppenud vead. Tõrketeade oli "pesitsevate tase liiga sügav – rekursiivne sõltuvus?"ja see võttis vähe aega

leida probleemi juur. Ma tegin seda valesti..

PHP on kaks võrdlus operaatorid, = = ja = = =. Üldiselt on teada, et esimene ei ole täpne tüüp, kuid teine on. Niisiis, näiteks

Echo ( FALSE = = 0 ); // Tõsi

Echo ( FALSE = = = 0 ); // Vale

– 0 on täisarv ja FALSE on Boolean

Minu probleem tekkis mitte-range kirjutades objekte.

$a = uus MyObj();
$b = uus MyObj();
Kui( $a = = $b )

Ma ei mõelnud, mida ma selle koodiga tegin.. Kui võrrelda kahte objekti, kasutades mitterange võrdluse korraldaja (==) PHP võrdleb objekte kõik omadused ja kui need vastavad objektid loetakse võrdseks. Kui nad ei vasta, ei ole nad võrdsed. Toime, Meil on rekursiivne võrdlus kõik omadused iga objekti, ja kõik nende omadused, Jne. kuni me jõuame põhilised andmetüübid nagu stringid ja täisja.

Kui, Kuid, Me kasutame range võrdluse (===), PHP kontrollib, kas need kaks objekti on täpselt sama objekt, mitte ainult objektid samade atribuutmetega.

klassi MyObj
{
avalik $p;
}

$a = uus MyObj();
$b = uus MyObj();
$c = uus MyObj();
$on>p = 1;
$b>p = 1;
$c>p = 2;
Echo ( $a = = $c ); // Vale
Echo ( $a = = $b ); // Tõsi
Echo ( $a = = = $b ); // Vale

Probleem tekib, kui teil on Ringviidete objektide atribuudid. Niisiis, näiteks

klassi MyObj
{
avalik $p;
}
klassi OtherObj
{
avalik $q;
}

$a = uus MyObj();
$b = uus OtherObj();
$on>p = $b;
$b>q = $a; // Ringviide: $on>lk>q = = = $a

$c = uus MyObj();
$d = uus OtherObj();
$c>p = $d;
$d>q = $c;// teine Ringviide: $c>lk>q = = = $c

Echo ( $a = = $c ); // Parandamatu tõrge:
Pesastustase on liiga sügav – rekursiivne sõltuvus?

Et võrrelda $a $c, PHP peab võrrelda oma omadusi. Nii et loogika PHP läheb midagi sellist: $a = = $c kui $a->p = = $c->p kui $a>lk>q = = $c->lk>q kui $a>lk>q>p = = $c->lk>q>p jne. Lõputult.

Php 5.1 tundus sujuvalt üle probleemi kuidagi (tõenäoliselt pärast teatud taseme rekordamine see lihtsalt tagastas vale) – ja tavaliselt toimis see hästi. Php 5.2 annab õigesti tulemuseks surmaga lõppeva vea.

Kui sa tead probleemi, lahendus on lihtne – kasutada range võrdlus.

Echo ( $a = = = $c ); // Vale (ja ei ole viga)

The strict comparison will simply check whether the two objects are at the same location in memory and so doesn’t even look at the values of the properties.

N.B. The same problem can arise when using the negated comparison operators (use !== instead of !=) and when using in_array (use in_array’s third parameter to indicate strict comparison).