¿Qué sucede si no llamo a fclose () en un progtwig C?

En primer lugar, soy consciente de que abrir un archivo con fopen () y no cerrarlo es terriblemente irresponsable y de mala calidad. Esto es pura curiosidad, así que por favor cántame 🙂

Sé que si un progtwig C abre un grupo de archivos y nunca cierra ninguno de ellos, eventualmente fopen () comenzará a fallar. ¿Hay algún otro efecto secundario que pueda causar problemas fuera del código mismo? Por ejemplo, si tengo un progtwig que abre un archivo y luego sale sin cerrarlo, ¿podría causar un problema a la persona que ejecuta el progtwig? ¿Podría un progtwig de ese tipo filtrar algo (memoria, manejadores de archivos)? ¿Podría haber problemas para acceder a ese archivo una vez que el progtwig haya finalizado? ¿Qué pasaría si el progtwig se ejecutara muchas veces seguidas?

    Mientras su progtwig se esté ejecutando, si continúa abriendo archivos sin cerrarlos, lo más probable es que se quede sin descriptores de archivo / identificadores disponibles para su proceso, y al intentar abrir más archivos fallará eventualmente. En Windows, esto también puede evitar que otros procesos abran o eliminen los archivos que haya abierto, ya que de forma predeterminada, los archivos se abren en un modo de uso compartido exclusivo que impide que otros procesos los abran.

    Una vez que su progtwig finalice, el sistema operativo se encargará de su limpieza. Cerrará todos los archivos que dejó abiertos cuando finalice su proceso, y realizará cualquier otra limpieza que sea necesaria (por ejemplo, si un archivo fue marcado como borrar-al-cerrar, entonces eliminará el archivo; tenga en cuenta que ese tipo de cosas son plataformas -específico).

    Sin embargo, otro problema a tener en cuenta es la información almacenada en el búfer . La mayoría de las secuencias de archivos almacenan los datos del búfer en la memoria antes de escribirlos en el disco. Si está utilizando secuencias FILE* de la biblioteca stdio, entonces hay dos posibilidades:

    1. Su progtwig salió normalmente, ya sea llamando a la función exit(3) o volviendo desde main (que implícitamente llama a exit(3) ).
    2. Su progtwig salió anormalmente; esto puede ser a través de llamadas abort(3) o _Exit(3) , muriendo a partir de una señal / excepción, etc.

    Si su progtwig salió normalmente, el tiempo de ejecución de C se encargará de enjuagar cualquier flujo de búfer que estuviera abierto. Por lo tanto, si ha almacenado datos almacenados en un FILE* que no se vació, se descargará en la salida normal.

    Por el contrario, si su progtwig salió anormalmente, los datos almacenados en el búfer no se eliminarán. El sistema operativo simplemente dice “¡Dios mío, dejaste un descriptor de archivo abierto, es mejor que lo cierre para ti” cuando el proceso finaliza; no tiene idea de que hay algunos datos aleatorios en algún lugar de la memoria que el progtwig intentó escribir en el disco pero no lo hizo. Así que ten cuidado con eso.

    El estándar C dice que llamar a exit (o, de manera equivalente, regresar desde main ) hace que todos los objetos FILE abiertos se cierren como si fclose . Así que esto está perfectamente bien, excepto que pierdes la oportunidad de detectar errores de escritura.

    EDITAR: No hay tal garantía para la terminación anómala ( abort , una assert fallida, la recepción de una señal cuyo comportamiento predeterminado es interrumpir el progtwig de manera anormal – tenga en cuenta que no hay necesariamente tales señales – y otros medios definidos por la implementación) ) Como han dicho otros, los sistemas operativos modernos limpiarán todos los recursos visibles externamente , como los manejadores de archivos de nivel de SO abiertos, independientemente; sin embargo, los FILE probablemente no se vaciarán en ese caso.

    Ciertamente ha habido sistemas operativos que no limpiaron los recursos externos visibles en la terminación anómala; tiende a ir junto con no aplicar límites de privilegios duros entre el código “kernel” y “usuario” y / o entre distintos “procesos” de espacio de usuario, simplemente porque si no tiene esos límites, puede que no sea posible hacerlo de forma segura en todos los casos. (Considere, por ejemplo, qué sucede si escribe basura sobre la tabla de archivos abiertos en MS-DOS, como puede hacerlo perfectamente).

    Suponiendo que sale bajo control, utilizando la llamada al sistema exit() o regresando de main() , las transmisiones abiertas de archivos se cierran después de la descarga. El estándar C (y POSIX) lo ordena.

    Si sale fuera de control (volcado de núcleo, SIGKILL), etc., o si usa _exit() o _Exit() , las secuencias de archivos abiertas no se vacían (pero los descriptores de archivo terminan cerrados, asumiendo un sistema POSIX-like con descriptores de archivos: el estándar C no exige descriptores de archivos). Tenga en cuenta que _Exit() es obligatorio según el estándar C99, pero _exit() es un mandato de POSIX (pero se comportan igual en los sistemas POSIX). Tenga en cuenta que los descriptores de archivos están separados de las secuencias de archivos. Consulte la discusión de ‘Consecuencias de la terminación del progtwig’ en la página POSIX para _exit() para ver qué sucede cuando un progtwig finaliza en Unix.

    Cuando el proceso muere, la mayoría de los sistemas operativos modernos (específicamente el kernel) liberarán todos sus identificadores y memoria asignada.