2012-06-07 12 views
5

Estoy un poco desconcertado si puedo ahorrar el comando fclose simplemente deshaciendo la variable que lleva el asa?¿Puedo cerrar un archivo deshaciendo el asa?

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

... // script goes on for a long 

comparación con:

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

... // script goes on for a long 

Insights alguien?

+2

yo no confiaría en que funcione constantemente a través de los sistemas operativos (sólo un presentimiento, aunque, no tengo evidencia de cualquier manera) –

+0

Sólo por curiosidad: ¿Cuál es la razón por la que elegirías 'unset' encima de' fclose'? – Nanne

+0

Pekka tiene razón, probé 'echo '$ fp es resource ='. (Is_resource ($ fp)? 'True': 'false');' Devuelve falso en máquina W2K, y en otros devuelve true – Sanjay

Respuesta

2

Los documentos PHP insinúan que todos los recursos sin referencias restantes se "liberan", supongo que para los manejadores de archivos esto incluiría el cierre del archivo.

caso de prueba simple:

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

(He guardado esto como test.php, por lo que es el bloqueo en sí; que tenga que cambiar el nombre del archivo en el fopen() a algún archivo existente de otra manera)

Run el guion dos veces en 5 segundos; si "sigues bloqueado", al parecer, al destrabar el asa no se suelta el candado. En mi prueba, hice no get "still locked", por lo que aparentemente desarmando el identificador al menos libera el bloqueo, aunque parecería tonto liberar bloqueos en la recolección de basura, pero no cerrar el archivo.

+0

¿Dónde los documentos PHP insinúan eso? Puede proporcionar un hipervínculo? – hakre

+0

[Recursos] (http://php.net/manual/en/language.types.resource.php), sección "Liberar recursos" – lanzz

+0

¿La liberación de un recurso en PHP cerrará el archivo-handle? – hakre

1

unset($handle) destruirá la variable $handle, pero no cerrará el archivo al que apunta el $handle. Aún necesita llamar al fclose() para cerrar el archivo.

+3

Me resulta difícil probar eso porque después de desconectar el controlador, no puedo usar 'fclose()' por más tiempo, ¿verdad? – hakre

+0

@hakre Lo que quiero decir es usar 'fclose ($ handle)' y no 'unset ($ handle)'. – flowfree

+1

Obviamente, pero me preocupa el razonamiento, no lo que es mejor. – hakre

0

algunas investigaciones:

fclose hace $handle sea resource(5) of type (Unknown) mientras

unset hace NULL.

y después de fclose php consume 88 bytes de memoria más.

manera: Son diferentes =)

+0

Usando la memoria para verificar eso. Diría que es interesante, pero esto necesita más elaboración para eliminar los efectos secundarios que se puedan imaginar. – hakre

+0

he usado 'memory_get_usage()' para obtenerlo – k102

+0

'unset' lo hace' Indefinido', no 'NULL'. – mpyw

3

Gracias al sistema de conteo de referencias introducido con PHP de 4 Zend Engine, un recurso sin más referencias a él se detecta automáticamente y se libera por la basura coleccionista.

Considere las implicaciones de esto. Es seguro suponer que todos los rastros de la variable se han ido después de la recolección de basura. En otras palabras, al final de la ejecución de PHP, si PHP aún no sigue la referencia, ¿cómo lo cerraría? Por lo tanto, parece bastante lógico que lo cerraría cuando el recolector de basura lo come.

Sin embargo, este es un argumento lógico incorrecto porque supone que las recolecciones de basura ocurren inmediatamente o poco después de la desinstalación y que PHP no mantiene referencias ocultas a las variables que ya no existen en el terreno del usuario.


Un caso más convincente, aunque podría ser un defecto de comportamiento potencial si PHP no se cerró identificadores de archivo cuando salen del ámbito de aplicación. Considera un daemon de algún tipo que abre muchos archivos.Ahora considere si fclose nunca se llama. En su lugar, se permite que las variables caigan fuera del alcance o se llame explícitamente a las variables.

Si estos identificadores de archivo no se cerraron, este daemon de ejecución larga se quedaría sin controladores de archivo.


Potencialmente comportamiento escritura de la prueba específica:

<?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 
} 

tanto en Windows 7 y Debian 6, la conexión se ha cerrado después del desarmado.

Obviamente, sin embargo, esto solo prueba que en mis máquinas específicas con mi versión específica de PHP funcionará esto. No tiene sentido en los manejadores de archivos o similares :).


Am buscar la fuente de PHP ahora para una prueba dura

+0

Los sockets no se manejan necesariamente de la misma forma que los archivos normales. No tiene sentido manejarlo de manera diferente, pero PHP a menudo no tiene sentido. – lanzz

+0

"No tiene sentido en los identificadores de archivo o similares :)." Sí ... Estoy tratando de seguir el código a través de la ruta de recogida de basura/destrucción de recursos ahora. – Corbin

Cuestiones relacionadas