2012-06-07 14 views
5

Sono un po 'perplesso se posso risparmiare il comando fclose semplicemente disinserendo la variabile che trasporta l'handle?Posso chiudere un file disattivando l'handle?

$handle = fopen($file); 
... 
fclose($handle); 

... // script goes on for a long 

Rispetto con:

$handle = fopen($file); 
... 
unset($handle); 

... // script goes on for a long 

Insights qualcuno?

+2

io non mi fiderei a farlo funzionare in modo coerente in tutta sistemi operativi (solo una sensazione viscerale anche se, non ho prove in entrambi i casi) –

+0

Solo curioso: qual è la ragione per cui sceglieresti 'unset' sopra' fclose'? – Nanne

+0

Pekka ha ragione, ho provato 'echo '$ fp è resource ='. (Is_resource ($ fp)? 'True': 'false');' Restituisce false sulla macchina W2K e in altri restituisce true – Sanjay

risposta

2

I documenti PHP suggeriscono che tutte le risorse senza riferimenti rimanenti sono "liberate", presumo che per gli handle di file ciò includa la chiusura del file.

Semplice test case:

$f = fopen("test.php", "r"); 
if (!flock($f, LOCK_EX)) { 
    print("still locked\n"); 
    exit; 
} 
unset($f); 
sleep(5); 
print("goodbye\n"); 

(Ho salvato questo come test.php, quindi è bloccaggio stesso; potrebbe essere necessario modificare il nome del file nella fopen() ad alcuni file esistente altrimenti)

Run la sceneggiatura due volte entro 5 secondi; se si ottiene "ancora bloccato", quindi apparentemente disinserire la maniglia non ha rilasciato il blocco. Nel mio test, ho effettuato non ottenere "ancora bloccato", quindi apparentemente disinserire la maniglia almeno rilascia il blocco, anche se sembrerebbe sciocco rilasciare i blocchi sulla garbage collection, ma non chiudere il file.

+0

Dove lo suggeriscono i documenti PHP? È possibile fornire un collegamento ipertestuale? – hakre

+0

[Risorse] (http://php.net/manual/en/language.types.resource.php), sezione "Liberare risorse" – lanzz

+0

La liberazione di una risorsa in PHP chiuderà l'handle di file? – hakre

1

unset($handle) distruggerà la variabile $handle, ma non chiuderà il file puntato da $handle. È comunque necessario chiamare fclose() per chiudere il file.

+3

Trovo difficile provare che, dopo aver disattivato l'handle, non posso più usare 'fclose()', giusto? – hakre

+0

@hakre Quello che intendo è usare 'fclose ($ handle)' e non 'unset ($ handle)'. – flowfree

+1

Ovviamente, ma sono preoccupato per il ragionamento, non per quello che è meglio. – hakre

0

qualche ricerca:

fclose rende $handle di essere resource(5) of type (Unknown) mentre

unset rende NULL.

e dopo fclose php consuma 88 byte di memoria in più.

così: essi sono differenti =)

+0

Utilizzare la memoria per verificarlo. Direi interessante, ma questo ha bisogno di più elaborazione in modo da rimuovere gli effetti collaterali che sono immaginabili. – hakre

+0

ho usato 'memory_get_usage()' per ottenerlo – k102

+0

'unset' lo rende' Undefined', non 'NULL'. – mpyw

3

Grazie al sistema di riferimento conteggio introdotta con PHP 4 Zend Engine, una risorsa con altri riferimenti ad esso viene rilevato automaticamente e viene liberato dalla spazzatura collettore.

Considerare le implicazioni di questo. È sicuro presumere che tutte le tracce della variabile siano scomparse dopo la garbage collection. In altre parole, alla fine dell'esecuzione di PHP, se PHP non sta ancora monitorando il riferimento, come lo chiuderà? Quindi, sembra abbastanza logico che lo chiuda quando il garbage collector lo mangia.

Questo è un argomento logico errato perché presuppone che le raccolte di dati inutili avvengano immediatamente o poco dopo l'eliminazione e che PHP non mantenga riferimenti nascosti a variabili che non esistono più nella terra dell'utente.


Un caso più convincente anche se potrebbe essere un potenziale difetto comportamentale se PHP non vicino handle di file quando vanno fuori portata. Considera un demone di qualche tipo che apre molti file.Considerare ora se fclose non viene mai chiamato. Invece, le variabili possono uscire dal campo di applicazione o unset viene esplicitamente richiamato su di esse.

Se questi handle di file non sono stati chiusi, questo daemon a esecuzione prolungata non ha più handle di file.


Potenzialmente comportamento specifico script di test:

<?php 

$db = mysql_connect(...); 

if ($db) { 
    echo "Connected\n"; 
    sleep(5); //netstat during this just for paranoia 
    unset($db); 
    echo "Unset\n"; 
    sleep(5); //netstat during this and the connection is closed 
} 

Su Windows 7 e Debian 6, la connessione è stata chiusa dopo il disinserimento.

Ovviamente, tuttavia, questo dimostra che sui miei computer specifici con la mia versione PHP specifica funzionerà. Non ha alcun significato sugli handle di file o simili :).


Cerco la sorgente PHP ora dura prova

+0

I socket non sono necessariamente gestiti come i file normali. Non ha senso gestirlo in modo diverso, ma PHP spesso non ha senso. – lanzz

+0

"Non ha alcun significato sugli handle di file o simili :)." Sì ... Sto provando a seguire il codice attraverso il percorso di cancellazione dei rifiuti/di scomposizione delle risorse ora. – Corbin

Problemi correlati