2011-01-26 20 views
41

Duplicar posible:
Do I need to manually close a ifstream?¿Debo cerrar un std :: fstream?

¿Es necesario llamar fstream.close() o es fstream un objeto RAII adecuado que se cierra el ciclo sobre la destrucción?

Tengo un objeto local std::ofstream dentro de un método. ¿Puedo suponer que el archivo siempre está cerrado después de salir de este método sin llamar a close? No pude encontrar la documentación del destructor.

+0

sí, es un duplicado. Gracias. No lo encontré. –

+3

No es un duplicado exacto. La pregunta a la que se hace referencia es específica de ifstreams, y esta generalmente trata sobre fstreams. –

Respuesta

65

Creo que las respuestas anteriores son engañosas.

fstreames un objeto RAII adecuada, hace se cierran automáticamente al final del alcance, y no hay absolutamente ninguna necesidad llamar close manualmente cuando se cierra al final del alcance es suficiente.

En particular, no es una "mejor práctica" y no es necesario enjuagar la salida.

Y si bien Drakosha tiene razón al llamar al close le da la posibilidad de verificar el bit de falla de la transmisión, nadie lo hace, de todos modos.

En un mundo ideal, uno simplemente llamaría stream.exception(ios::failbit) de antemano y manejaría la excepción que se arroja en un destructor fstream. Pero desafortunadamente las excepciones en destructores son un concepto roto en C++, por lo que no es una buena idea.

Así que si desea comprobar el éxito del cierre de un archivo, hágalo manualmente (pero solo entonces).

+4

En realidad compruebo el resultado cercano cada vez, porque estoy trabajando en una aplicación que debe garantizar que los datos se confirmen en el disco. Además, un poco fuera de lugar, ** close no garantiza el color ** (al menos en Linux), y no estoy seguro de que el destructor se descargue. De hecho, diría que es una "buena práctica" limpiar y cerrar, y verificar los errores en ambos. – Drakosha

+7

@Drakosha: asegurarse de que los datos se descarguen hasta el disco es una cosa completamente diferente de lo que garantiza 'flush' o' close'. Lo mejor que puede suponer en general es que 'flush' saca los datos del proceso y los coloca en el nivel del sistema operativo, por ejemplo, matar el proceso no evitará que se escriban los datos. No hay API portátil para garantizar que los datos estén comprometidos con el almacenamiento persistente, ya que el estándar C++ no tiene un concepto de almacenamiento persistente en comparación con otro almacenamiento presentado como (parte de) un sistema de archivos. –

+1

También estoy un poco sorprendido por el comportamiento de Linux. Se requiere que el destructor fstream llame a la función de miembro 'close',' close' es necesario para cerrar "como si fuera' fclose' ", y' fclose' se define para purgar la secuencia. Por lo tanto, el destructor ciertamente debe enjuagar, aunque el enjuague puede no hacer necesariamente lo que usted desea si existe el riesgo de que el enchufe se enganche en la máquina. Necesitas ('non-standard-C++)' fsync' para eso. –

1

creo que es una buena práctica para cerrar su fstream, causa que necesita para vaciar el búfer, que lo que me han dicho

+5

si fstream es un objeto RAII, se cerrará y, por lo tanto, los búferes se vacían de todos modos. La pregunta principal es si necesito el manejo de errores en todos los flujos de control para asegurar que se purgue. –

+4

Lo siento, -1 solo porque de alguna manera tenía +2. Liberar manualmente un recurso es un signo de mala programación o un malentendido sobre el propósito de un contenedor. – GManNickG

+0

@GMan: Yo diría que no preocuparse si su archivo se cerró correctamente es el caso excepcional, y debe llamar 'close()' usted mismo en la mayoría de las situaciones. * Lejos * demasiados desarrolladores de software hacen suposiciones que yo preferiría que no tuvieran sobre la confiabilidad y disponibilidad de los sistemas de archivos de los usuarios. –

6

Para añadir a la respuesta de Amy Lee, es mejor hacerlo de forma manual porque de esta manera también puedes verificar si hay errores.

Por cierto, de acuerdo con "close" manpage:

No comprobar el valor de retorno de close() es una común, pero sin embargo grave error de programación. Es bastante posible que los errores en una operación de escritura anterior primero se informen en el cierre final(). Si no se verifica el valor de retorno al cerrar el archivo, es posible que provoque una pérdida de datos silenciosa. Esto puede especialmente observar con NFS y con cuota de disco.

Un cierre exitoso no garantiza que los datos han sido exitosamente guardado en el disco, como el núcleo difiere escribe. No es habitual que un sistema de archivos vacíe los búferes cuando se cierra la secuencia. Si necesita , asegúrese de que los datos estén físicamente almacenados, use fsync (2). (Dependerá de en el hardware del disco en este momento).

+1

Es mejor hacerlo manualmente * si * necesita verificar errores, esto no significa que debamos * siempre * cerrar manualmente. No se puede hacer una práctica general a partir de un caso excepcional. En el caso general, cuando se está cerrando, no nos importa cómo haya tenido éxito, así que déjalo ir automáticamente. – GManNickG

+3

@GMan: si no está buscando errores, esto significa que está engañando a su usuario de que los datos están en el disco mientras que no lo está. – Drakosha

+1

@Drakisha: Pero, como dice Steve, una vez que cierro (lo cual se hace automáticamente), error o no está fuera de mis manos. También su "aumento" es C++ no estándar, estamos hablando de C++ estándar 'fstream' aquí. – GManNickG

Cuestiones relacionadas