El almacenamiento en búfer de entrada/salida (IO buffering) ha estado presente en el lenguaje C desde la aparición de la biblioteca estándar (stdio). Se introdujo para mejorar el rendimiento de las operaciones de lectura y escritura, ya que las solicitudes a disco o dispositivos son operaciones costosas en tiempo, y el almacenamiento en búfer permite reducir su cantidad.
La falta de comprensión del funcionamiento del almacenamiento en búfer puede llevar a retrasos inesperados en la entrada/salida, pérdida de datos en caso de un cierre inesperado del programa, errores al trabajar con múltiples hilos (especialmente con stdout/stderr), así como errores de sincronización entre procesos o sistemas.
Sabiendo que los flujos de archivos pueden estar almacenados en búfer, ser almacenados en búfer de forma lineal o no estar almacenados en búfer, es importante utilizar funciones de vaciado forzado del búfer (fflush()), cerrar correctamente los archivos (fclose()), y combinar adecuadamente el trabajo con stdin, stdout y stderr. El almacenamiento en búfer también depende del tipo de flujo (por ejemplo, stdout se vacía al imprimir el carácter en flujos asociados a un terminal, pero no siempre — si es un archivo).
Ejemplo de código:
#include <stdio.h> int main() { printf("Hola"); // sleep(10); // no habrá salida hasta fflush fflush(stdout); // muestra inmediatamente el búfer en pantalla return 0; }
Características clave:
fflush() — herramienta principal para vaciar el búfer manualmente.¿Se puede confiar en que la salida de printf aparecerá inmediatamente en la pantalla?
No, si la salida va a un archivo, por ejemplo, las líneas no aparecerán hasta que se produzca un vaciado del búfer, o hasta que se alcance el límite de búfer. Incluso en el terminal, una línea sin puede no aparecer de inmediato. Utilice fflush(stdout); para una salida inmediata.
¿Qué sucederá si se llama a fflush(stdin)?
Eso es comportamiento indefinido según el estándar de C. Algunos compiladores/plataformas pueden limpiar el búfer del flujo de entrada, pero esto no está garantizado por el estándar, y este enfoque no es portable y potencialmente peligroso.
¿Se pueden considerar printf y fprintf(stderr, ...) equivalentes para una salida inmediata?
No. La salida estándar (stdout) generalmente se almacena en búfer completamente o por líneas, stderr por estándar siempre se almacena en búfer de manera no segura. Es decir, la salida en stderr aparece en pantalla de inmediato, mientras que en stdout no.
fflush(stdin) para limpiar el búfer de entrada.El programa escribe un archivo de registro a través de printf, pero no llama a fflush(stdout) y no cierra el archivo en caso de cierre inesperado.
Ventajas:
Desventajas:
El programa llama a fflush(stdout) después de cada registro de log importante, o escribe mensajes críticos en stderr.
Ventajas:
Desventajas: