Domanda

In PHP5, il metodo __destruct () è garantito per essere chiamato per ogni istanza di oggetto? Le eccezioni nel programma possono impedire che ciò accada?

È stato utile?

Soluzione

Il distruttore verrà chiamato quando tutti i riferimenti vengono liberati o quando termina lo script. Presumo che ciò significhi quando lo script termina correttamente. Direi che le eccezioni critiche non garantirebbero il richiamo del distruttore.

La documentazione PHP è un po 'sottile, ma dice che le eccezioni nel distruttore causeranno problemi.

Altri suggerimenti

Vale anche la pena ricordare che, nel caso di una sottoclasse che ha un proprio distruttore, il distruttore genitore non è non chiamato automaticamente.

Devi chiamare esplicitamente parent :: __ destruct () dal metodo della sottoclasse __destruct () se la classe genitore esegue la pulizia richiesta.

Nella mia esperienza i distruttori saranno sempre chiamati in PHP 5.3, ma ti avvisiamo che se un pezzo di codice chiama exit () o se si verifica un errore fatale, PHP chiamerà i distruttori in " any " ordine (penso che l'ordine reale sia l'ordine in memoria o l'ordine in cui la memoria era riservata agli oggetti. In pratica, questo ordine è quasi sempre problematico). Questo è indicato come "sequenza di spegnimento" nella documentazione di PHP.

La documentazione PHP dei distruttori dice:

  

PHP 5 introduce un concetto di distruttore simile a quello di altri linguaggi orientati agli oggetti, come C ++. Il metodo distruttore verrà chiamato non appena non ci sono altri riferimenti a un particolare oggetto o in qualsiasi ordine durante la sequenza di spegnimento.

Di conseguenza se si dispone della classe X che contiene un riferimento a Y, il distruttore di X può essere chiamato DOPO che il distruttore di Y è già stato chiamato. Spero che il riferimento a Y non sia stato così importante ... Ufficialmente questo non è un bug perché è stato documentato.

Tuttavia, è molto difficile risolvere questo problema perché ufficialmente PHP non fornisce alcun modo per sapere se i distruttori sono chiamati normalmente (i distruttori sono chiamati nell'ordine corretto) o i distruttori sono chiamati in " qualsiasi " ordine in cui non è possibile utilizzare i dati dagli oggetti referenziati perché potrebbero essere già stati distrutti. Si potrebbe aggirare questa mancanza di rilevamento usando debug_backtrace () ed esaminando lo stack. La mancanza di stack normale sembra implicare "sequenza di spegnimento" con PHP 5.3 ma anche questo non è definito. Se hai riferimenti circolari, i distruttori di quegli oggetti non saranno chiamati affatto con PHP 5.2 o inferiore e saranno chiamati in "qualsiasi" ordine durante " sequenza di spegnimento " in PHP 5.3 o versioni successive. Per i riferimenti circolari, non esiste un "corretto" logico ordina così " qualsiasi " l'ordine è buono per quelli.

Ci sono alcune eccezioni (dopo tutto questo è PHP):

  • se exit () viene chiamato in un altro distruttore, i rimanenti distruttori non verranno chiamati ( http://php.net/manual/en/language.oop5.decon.php )
  • se l'errore FATAL si verifica ovunque (molte cause possibili, ad esempio il tentativo di eliminare un'eccezione da qualsiasi altro distruttore potrebbe essere una causa), i distruttori rimanenti non verranno chiamati.

Naturalmente, se il motore PHP rileva un errore di segmentazione o si verifica qualche altro bug interno, allora tutte le scommesse sono disattivate.

Se desideri comprendere l'implementazione attuale di " sequenza di spegnimento " ;, vedi https://stackoverflow.com / a / 14101767 . Nota che questa implementazione potrebbe cambiare nelle future versioni di PHP.

Esiste un bug corrente con riferimenti circolari che interrompe il metodo di distruzione in modo implicito. http://bugs.php.net/bug.php?id=33595 Dovrebbe essere risolto in 5.3

Usa una funzione di spegnimento se vuoi andare di sicuro: register_shutdown_function ( )

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top