====== setvbuf() ====== ''setvbuf()'' ist in der ''[[c:lib:stdio:start|stdio]]'' definiert, die in C über ''stdio.h'', bzw in C++ über ''cstdio'' eingebunden wird. ===== Funktion ===== ''setvbuf()'' gibt den IO-Buffer an, der für den ''FILE''-Stream verwendet werden soll. Wird [[c:lib:stddef: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 Buffer 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. Dateien werden automatisch einem Puffer ausgestattet. ''[[stdin]]'', ''[[stdout]]'' und ''[[stderr]]'' sind ohne Puffer ausgelegt, um Ausgaben sofort an die Konsole liefern zu können. ===== Signatur ===== #include void setvbuf( FILE * stream, char * buffer, int mode, size_t size ); **stream**: der zu konfigurierende Stream\\ **buffer**: Zeiger auf den Speicherbereich, der als Puffer dienen soll oder [[c:lib:stddef:null|NULL]] \\ **mode**: beschreibt, wie der Stream gepuffert werden soll \\ **size**: Größe des Puffers \\ Folgende Modes stehen zur Verfügung: ^ mode ^ Beschreibung ^ | _IONBF | No Buffer - keinen Puffer verwenden | | _IOLBF | Line Buffered - Zeilenweise zwischenspeichern | | _IOFBF | Fully Buffered - Block Puffer verwenden | Wird als ''buffer'' [[c:lib:stddef:null|NULL]] übergeben, so wird bei ''_IONBF'' nicht gepuffert, bei ''_IOLBF'' und ''_IOFBF'' wird automatisch ein Puffer der Größe ''[[BUFSIZE]]'' angelegt. ===== Fehlerquellen ===== ''buffer'' muss mindestens so groß sein, wie in ''size'' angegeben. ''setvbuf()'' 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 ''setvbuf()'' den Puffer auf [[c:lib:stddef:null|NULL]], die Größe auf 0, sowie den Modus auf ''_IONBF'' 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 #include int main (void) { FILE *file = fopen("logfile.txt", "w+"); /* Kommentar in der nächsten Zeile entfernen, um zuverlässig Logfiles zu schreiben */ // setvbuf( file, NULL, _IONBF, 0 ); fprintf( file, "vor Absturz" ); /* Absturz provozieren */ *((int *)0) = 4711; /* Dieser Part wird nicht mehr erreicht */ fprintf( file, "nach Absturz" ); fclose(file); return EXIT_SUCCESS; } Statt den Puffer komplett abzuschalten, kann man auch den Befehl ''[[fflush()]]'' verwenden. Ein entsprechend verändertes Beispiel findet sich dort. ===== Hinweis ===== Das Beispielprogramm stürzt absichtlich ab! Es zeigt den Unterschied zwischen einer gepufferten Datei im Fall eines Absturzes und der ungepufferten Datei. Ist ''setvbuf()'' 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 ''setvbuf()'' 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 ===== [[c:lib:stdio:start|stdio]]: [[c:lib:stdio:fflush()]], [[c:lib:stdio:fclose()]], [[c:lib:stdio:setbuf()]]