Il buffering dell'input/output (IO buffering) è presente nel linguaggio C sin dall'apparizione della libreria standard (stdio). È stato introdotto per migliorare le prestazioni delle operazioni di lettura e scrittura, poiché gli accessi al disco o ai dispositivi sono operazioni costose in termini di tempo, e il buffering consente di ridurre il loro numero.
Non comprendere il funzionamento del buffering può portare a ritardi inaspettati nell'input/output, perdita di dati in caso di interruzione improvvisa del programma, errori nel lavoro con più thread (soprattutto con stdout/stderr) e anche errori di sincronizzazione tra processi o sistemi.
Sapendo che i flussi di file possono essere bufferizzati, linearmente bufferizzati o non bufferizzati, è importante utilizzare funzioni di flush forzato del buffer (fflush()), chiudere correttamente i file (fclose()) e combinare correttamente il lavoro con stdin, stdout e stderr. Il buffering dipende anche dal tipo di flusso (ad esempio, stdout viene flushato quando viene stampato il carattere in un flusso collegato a un terminale, ma non sempre — se si tratta di un file).
Esempio di codice:
#include <stdio.h> int main() { printf("Hello"); // sleep(10); // senza fflush non ci sarà output fflush(stdout); // stampa subito il buffer sullo schermo return 0; }
Caratteristiche chiave:
fflush() — strumento principale per il flush manuale del buffer.Si può contare sul fatto che l'output di printf apparirà subito sullo schermo?
No, se l'output va a un file, ad esempio, le righe non appariranno finché non ci sarà un flush del buffer, o finché non si raggiunge il limite del buffer. Anche nel terminale, una riga senza potrebbe non apparire immediatamente. Utilizza fflush(stdout); per un output immediato.
Cosa accade se si chiama fflush(stdin)?
Questo è comportamento indefinito secondo lo standard C. Alcuni compilatori/ piattaforme possono pulire il buffer del flusso di input, ma non è garantito dallo standard, e tale pratica non è portabile e potenzialmente pericolosa.
Possono printf e fprintf(stderr, ...) essere considerati equivalenti per un output immediato?
No. L'output standard (stdout) è generalmente completamente o l'output per riga, stderr per standard è sempre non bufferizzato. Quindi, l'output in stderr appare immediatamente sullo schermo, mentre in stdout no.
fflush(stdin) per pulire il buffer di input.Un programma scrive un file di log tramite printf, ma non chiama fflush(stdout) e non chiude il file in caso di interruzione.
Vantaggi:
Svantaggi:
Un programma chiama fflush(stdout) dopo ogni importante registrazione di log, oppure scrive messaggi critici in stderr.
Vantaggi:
Svantaggi: