setbuf()

setbuf() ist in der stdio definiert, die in C über stdio.h, bzw in C++ über cstdio eingebunden wird.

Funktion

setbuf() gibt den IO-Buffer an, der für den FILE-Stream verwendet werden soll. Wird NULL übergeben, so wird der Stream nicht gepuffert.

Gepufferte Streams werden nicht sofort auf die Festplatte geschrieben, sondern Lese- und Schreibvorgänge werden zunächst im Puffer gesammelt. Da Dateisysteme Daten in Blöcken ablegen, werden pro Schreibzugriff in der Regel 512 Bytes geschrieben. Würde ein Byte geändert, so muss der vorhandene Block gelesen, verändert und auf das Dateisystem zurückgeschrieben werden. Schreibt man nun Buchstabe für Buchstabe, bedeutet das extrem viel Aufwand, so dass zunächst in einen Puffer geschrieben wird. Wenn der Puffer voll ist, werden die gesammelten Daten an einem Stück übertragen. Wird die Datei mit fclose() geschlossen, so werden alle noch nicht geschriebenen Daten zunächst auf die Festplatte kopiert. Dies lässt sich auch künstlich durch die fflush()-Anweisung auslösen, ohne die Datei zu schließen.

Einige Betriebssysteme unterscheiden zwischen zeichen- und zeilenorientierten Streams. Für zeilenorientierte Streams ist die setvbuf()-Funktion zu verwenden.

Dateien werden automatisch mit einem Puffer ausgestattet. stdin, stdout und stderr sind ohne Buffer ausgelegt, um Ausgaben sofort an die Konsole liefern zu können.

Signatur

#include <stdio.h>
void setbuf( FILE * stream, char * buffer );

stream: der zu konfigurierende Stream
buffer: Zeiger auf den Speicherbereich, der als Puffer dienen soll oder NULL, für ungepufferte Ausgaben

Fehlerquellen

buffer muss mindestens so groß sein, wie in BUFSIZ angegeben.

setbuf() sollte direkt nachdem die Datei geöffnet wurde und bevor irgendeine Ein- oder Ausgabe über den Stream gelaufen ist.

Sobald Streams gepuffert werden, werden Schreibzugriffe nicht mehr sofort auf den Datenträger geschrieben, sondern zunächst im Puffer gesammelt und anschließend in einem Zug auf den Datenträger geschrieben. Wird die Datei nicht ordnungsgemäß geschlossen, zum Beispiel durch einen Programmabsturz, so werden die Daten, die zunächst im Puffer zwischengespeichert wurden nicht mehr auf den Datenträger geschrieben. Das kann bei der Suche nach dem Fehler eine falsche Spur legen, da Ausgaben, die das Programm gemacht hat, in der Datei nicht mehr auftauchen und man so den Absturz an der Stelle vermutet, an der das Programm den letzten Eintrag in die Datei gesendet hat. Gerade für Log-Files empfiehlt es sich daher, mit setbuf() den Puffer auf NULL zu setzen und damit zu deaktivieren.

Da Programme normalerweise nicht abstürzen sollten, hilft der aktivierte Cache bei korrekten Programmen Lese- und Schreibvorgänge mit wenigen Daten deutlich zu beschleunigen.

Beispiel

#include <stdlib.h>
#include <stdio.h>
 
int main (void)
{
  FILE *file = fopen("logfile.txt", "w+");
 
  /* Kommentar in der nächsten Zeile entfernen, um zuverlässig Logfiles zu schreiben */
  // setbuf( file, NULL );
 
  fprintf( file, "vor Absturz" );
 
  /* Absturz provozieren */ 
  *((int *)0) = 4711;
 
  /* Dieser Part wird nicht mehr erreicht */
  fprintf( file, "nach Absturz" );
 
  fclose(file);
  return EXIT_SUCCESS;
}

Hinweis

Das Beispielprogramm stürzt absichtlich ab! Es zeigt den Unterschied zwischen einer gepufferten Datei im Fall eines Absturzes und der ungepufferten Datei. Ist setbuf() auskommentiert, wird eine Datei logfile.txt angelegt, die aber nicht mehr beschrieben wird, obwohl der Text „vor Absturz“ zuvor geschrieben werden sollte. Die Dateigröße ist 0. Wird setbuf() aufgerufen, so wird der Text „vor Absturz“ auf die Festplatte geschrieben, bevor das Programm in seiner Berechnung fehlschlägt und abstürzt.

Die Funktion setbuf() entspricht dem folgenden Aufruf der Funktion setvbuf():

setvbuf( stream, buffer, buffer ? _IOFBF : _IONBF, BUFSIZ );

siehe auch