[ Webhosting profitux.cz ]
v6ak [ programování, bezpečnost, web, php, java, ... ] (Vít Šesták)
Buzz - v6ak Twitter - v6ak

štítky

Když se objekt nezničí...

Nedávno jsem měl s objektem v php5 problém - nechtěl včas volat destruktor. Už vím, čím to bylo.

Představte si následující:

class x{ private $_me; function __construct(){ $this->_me = $this; } function __destruct(){ echo 'končím'."\n"; } } $x=new x(); unset($x); echo 'smazáno'."\n";

Co se stane? Myslíte si, že by se po unset($x) měl zavolat destruktor? Zkuste si to! Nejdřív napíše 'smazáno' a potom teprve 'končím'. Takže se destruktor nezavolal! Jakto?

Kdy se volá destruktor?

Když jsem se pro jistotu podíval do manuálu php na konstruktory a destruktory, ze začátku jsem z toho nebyl moudřejší. Destruktor se má zavolat když na daný objekt neukazuje žádný ukazatel. A potom se ostatní objekty destruují při ukončení php skriptu.

V tom je právě ten problém - $x není jediný ukazatel na můj objekt. Takže nepomůže ani explicitní dealokace unset($x), protože tím dealokuji jen jeden pointer. Druhý ale zůstává v (privátní) proměnné $x->_me! (Jasně, takto k ní nemůžu přistupovat, dokonce ze dvou důvodů. Já k ní vlastně nemůžu vůbec přistupovat. Nemám na ní žádný ukazatel, ten má jen sama na sebe.)

Dopad

Může to způsobit dva problémy:

Závažnost obou záleží na konkrétní situaci. Pokud se smějete memoryleaku, že se stejně za chviličku uvolní, pak asi používáte php jen pro webové stránky. Třeba u php bota by to mohlo vadit.

Pokud však destruktor má jiný význam než dealokaci paměti, pak to může být docela velký problém. Typickým příkladem může být dočasné nahrazení obsluhy nějaké události, které v destruktoru vracíte zpět. A dokonce může být i příčinou problematického zpětného odkazu na objekt. Představte si, že chcete nastavit obsluhu události takto:

setAHandler(array($this, '_aHandler'));

Pak je sice hezké, že v destruktoru to vracíte do původního stavu, ale máte zde v callbacku kopii pointeru na $this, takže se destruktor nezavolá, protože na něj bude furt aspoň jeden pointer...

Řešení

Dočasný handler

V případě dočasného handleru existují dvě možná řešení:

A mám paměť uvolňenou!

Obecná doporučení

Diskuzi ke článku naleznete zde.

Linkování

Líbí se Vám tato stránka? Zalinkujte ji!

Chcete sledovat novinky? Pokud si právě prohlížíte článek a hledáte RSS pro celý web, pak jste trošku jinde. Možná hledáte poslední změny.

Validní HTML 4.01 StrictValidní CSS 2.0Validní hlavní RSS kanálPHP 5Apache
referer: UA:CCBot/2.0 (http://commoncrawl.org/faq/) time:0.98897200 1495508667
web
mail
comment