Archive for the ‘Module’ flokkur

PHP villa hreiðurstig of djúpt endurkvæmt ósjálfstæði

12. mars, 2010

Ég hef sett upp PHP 5.2 á einni af prófunartölvunum mínum í dag og nokkrum bitum af kóða sem áður virkaði fínt í útgáfu 5.1.6 kastaði banvænum villum í nýju útgáfunni. Villuboðin voru "Hreiðurstig of djúpt – endurkvæm ósjálfstæði?" og það tók smá tíma

að hafa uppi á rót vandans. Hér er það sem ég hafði gert rangt.

Í PHP eru tveir samanburðaraðilar, == og ===. Það er almennt vitað að sá fyrri er ekki strangur um gerð en sá síðari er. Svo, Til dæmis

bergmál ( rangt == 0 ); // sannur

bergmál ( ósatt === 0 ); // falskur

– 0 er heiltala og ósatt er boolean

Vandamálið mitt kom upp af því að nota ekki stranga vélritun með hlutum.

$a = nýr MyObj();
$b = nýr MyObj();
ef( $a == $b )

Ég hafði ekki íhugað hvað ég var að gera með þessum kóða. Þegar tveir hlutir eru bornir saman með því að nota ósamræmda samanburðaraðilann (==) PHP ber saman alla eiginleika hlutanna og ef þeir passa við hlutina eru taldir vera jafnir. Ef þeir passa ekki saman eru þeir ekki jafnir. Í gildi, við höfum endurkvæman samanburð á öllum eiginleikum hvers hlutar, og allar eignir þeirra, o.s.frv. þar til við náum grunngagnagerðum eins og strengjum og heiltölum.

Ef, hins vegar, við notum strangan samanburð (===), PHP mun athuga hvort hlutirnir tveir séu nákvæmlega sami hluturinn, ekki bara hlutir með sömu eiginleika.

flokkur MyObj
{
opinber $p;
}

$a = nýr MyObj();
$b = nýr MyObj();
$c = nýr MyObj();
$a->p = 1;
$b->p = 1;
$c->p = 2;
bergmál ( $a == $c ); // falskur
bergmál ( $a == $b ); // sannur
bergmál ( $a === $b ); // falskur

Vandamálið kemur upp ef þú ert með hringlaga tilvísanir í eiginleika hlutanna þinna. Svo, Til dæmis

flokkur MyObj
{
opinber $p;
}
flokkur OtherObj
{
opinber $q;
}

$a = nýr MyObj();
$b = nýr OtherObj();
$a->p = $b;
$b->q = $a; // hringlaga tilvísunin: $a->p->q === $a

$c = nýr MyObj();
$d = nýr OtherObj();
$c->p = $d;
$d->q = $c;// önnur hringlaga tilvísun: $c->p->q === $c

bergmál ( $a == $c ); // Banvæn villa:
Hreiðurstig of djúpt – endurkvæm ósjálfstæði?

Til að bera $a saman við $c, PHP verður að bera saman eiginleika þeirra. Þannig að rökfræðin í PHP fer eitthvað svona: $a == $c ef $a->p == $c->p ef $a->p->q == $c->p->q ef $a->p->q->p == $c->p->q->p osfrv.. Endalaust.

PHP 5.1 virtist slétta yfir vandamálið einhvern veginn (líklega eftir ákveðinn samdrátt skilaði það einfaldlega röngu) – og yfirleitt gekk þetta ágætlega. PHP 5.2 rétt framleiðir banvæna villu hér að ofan.

Þegar þú veist vandamálið, lausnin er auðveld – notaðu strangan samanburð.

bergmál ( $a === $c ); // falskur (og engin villa)

Strangur samanburður mun einfaldlega athuga hvort hlutirnir tveir séu á sama stað í minni og lítur því ekki einu sinni á gildi eiginleikanna.

N.B.B.. Sama vandamál getur komið upp þegar notaðir eru neituðu samanburðaraðilarnir (nota !== í stað !=) og þegar in_array er notað (notaðu þriðju breytu in_array til að gefa til kynna strangan samanburð).