Unterschied zwischen cerr und cout
-
Hallo wi liegt der Unterschied ziwschen:
cerr<<
und
cout<<
-
std::cout
ist ein gepufferter Stream, das heisst, nicht jedes Zeichen kommt sofort auf die Konsole, sondern es kommt zu einer Zwischenspeicherung, sodass mehrere Zeichen miteinander ausgegeben werden können (was zu Performancevorteilen führt).std::cerr
hingegen ist nicht gepuffert, und deshalb für Fehlerausgaben geeignet (wenn z.B. das Programm mitten in der Ausgabe hängen bleibt, dass trotzdem so viel wie möglich ausgegeben wird).
-
cout schreibt standardmaessig nach stdout und cerr nach stderr...
-
Und es gibt noch
clog
, was auch nachstderr
schreibt.
Viel wichtiger dabei anzumerken ist wohl, dassstdout
undstderr
nicht unbedingt mit dem gleichen Output verbunden sind. Also wenn man mitcout
auf der Konsole etwas ausgibt, dann muss es nicht heissen, dass mitcerr
oderclog
auf der gleichen Konsole die Ausgabe erscheint. Es muss nicht mal in einer Konsole sein.Grüssli
-
Dravere schrieb:
...
Viel wichtiger dabei anzumerken ist wohl, dassstdout
undstderr
nicht unbedingt mit dem gleichen Output verbunden sind...Das finde das eine ganz wichtige (neben der "Unsychronisiertheit" vielleicht wichtigste) Eigenschaft.
Bei unseren Programmen nutzen wir cerr zum Logging und leiten den Output standardmäßig in ein File um. cout ist im produktiven Betrieb abgeschaltet (und zur Sicherheit nach /dev/null abgebogen) - das kann man nur während der Entwicklungsphase individuell für Tests nutzen.Gruß,
Simon2.
-
Sry dass ich so n altes Thema wieder aufgreife, habs aber beim googeln gefunden.
1.std::cout ist ein gepufferter Stream, das heisst, nicht jedes Zeichen kommt sofort auf die Konsole
und was ist wenn ich std::cout << "..." << std::endl mache?
2.
Und was genau ist jetzt eigentlich der Unterschied zwischen std::clog u. std::cerr?MfG
Stromber
-
Stromberg schrieb:
und was ist wenn ich std::cout << "..." << std::endl mache?
std::endl flusht nach dem Zeilenumbruch den Stream, leert also den Puffer und erzwingt die Ausgabe. Wenn allerdings die Ausgabe nach dem zweiten Puntk hängen bleibt, stehen bei cerr dann eben zwei Punkte da, bei cout nichts.
-
Und was ist der Unterschied zwischen cerr und clog?
MfG
Stromberg
-
Hast Du schon mal was von Suchmaschinen gehört?
-
Tut mir leid, hab nix gefunden.
Also ich weiß dass cerr, ungepuffert ist, und clog nicht. Aber dass interessiert mich auch nicht.
Ich frage mal anders, was ist der Sinn von clog? Wann setzt man es ein? Was bewirkt es?MfG
Stromberg
-
std::cerr
undstd::clog
gehen per Default nachstderr
. Du kannst aber selber etwas damit verbinden, das ist dir freigestellt.#include <fstream> #include <iostream> int main() { std::filebuf logBuf; std::filebuf errBuf; logBuf.open("log.txt", std::ios::out); errBuf.open("err.txt", std::ios::out); std::clog.rdbuf(logBuf); std::cerr.rdbuf(errBuf); std::cout << "Hallo!" << std::endl; std::clog << "Meldung!" << std::endl; std::cerr << "Fehler!" << std::endl; return 0; }
Und was der Unterschied zwischen einem Log und einem Error ist, nehme ich mal an, dass du das weisst.
Grüssli
-
Also den Sinn von clog verstehe ich immer noch nicht so ganz. Gut wenn ich dass richtig verstanden habe, wird in dem Codebeispiel dann einfach bei Aufruf von clog, alles in "log.txt" reingeschrieben. Dann könnte ich aber auch einfach ein "ostream datei" Objekt verwenden oder?
Und was der Unterschwied zwischen einem Error und Log ist, ja mh, Error is halt eine Fehlermeldung, und log ein Protokoll?MfG
Stromberg
-
Stromberg schrieb:
Dann könnte ich aber auch einfach ein "ostream datei" Objekt verwenden oder?
Ja, könntest du. Nur hast du mit
std::clog
ein per Standard bereits existierendes Objekt, welches in allen Übersetzungeinheiten verfügbar ist. Man muss nur<iostream>
inkludieren.Stromberg schrieb:
Und was der Unterschwied zwischen einem Error und Log ist, ja mh, Error is halt eine Fehlermeldung, und log ein Protokoll?
Und ist dir der Unterschied dazwischen bewusst? Eine Fehlermeldung kommt dann, wenn etwas schief lief. Ein Protokoll protokolliert aber nicht nur Dinge, welche schief gelaufen sind. Es können dort auch Meldungen über erfolgreich ausgeführte Aufgaben abgelegt werden. Oder auch einfach nur Hinweise, was das Programm gerade macht. Warnings, also Warnungen, würde ich z.B. auch in ein Protokoll eintragen. Warnungen sind schliesslich keine Fehler.
Du hast also schlussendlich die folgenden Streams:
Eingabe
Ausgabe
Fehler Protokoll
Allgemeines ProtokollGrüssli
-
Das Beispielprogramm compiliert besser wenn es so aussieht:
rdbuf( & ... )
stattrdbuf( ... )
int main() { std::filebuf logBuf; std::filebuf errBuf; logBuf.open("log.txt", std::ios::out); errBuf.open("err.txt", std::ios::out); std::clog.rdbuf( [b]&[/b]logBuf ); std::cerr.rdbuf( [b]&[/b]errBuf ); std::cout << "Hallo!" << std::endl; std::clog << "Meldung!" << std::endl; std::cerr << "Fehler!" << std::endl; logBuf.close(); // Ist das saubere Schliessen nicht auch sinnvoll? errBuf.close(); return 0; }
Mit g++ (4.2.1) bekomme ich beim Verlassen des Programms einen
Segmentation Fault. Der Stack sieht dann so aus:(gdb) info stack
#0 0xb7fa5ff4 in ?? () from /usr/lib/libstdc++.so.6
#1 0xb7f47542 in std::ostream::flush () from /usr/lib/libstdc++.so.6
#2 0xb7f0eddd in std::ios_base::Init::~Init () from /usr/lib/libstdc++.so.6
#3 0x08048b9e in __tcf_0 () at /usr/include/c++/4.2.1/iostream:77
#4 0xb7d67599 in exit () from /lib/libc.so.6
#5 0xb7d50fe8 in __libc_start_main () from /lib/libc.so.6
#6 0x080489c1 in _start ()Hat da jemand einen Plan was da noch immer schief hängt?
-
Einen Plan habe ich nicht aber eine Vermutung.
clog ist ein statisches Objekt und der Destruktor wird erst aufgerufen, wenn die Funktion main schon beendet ist. logBuf ist dagegen innerhalb der Funktion main definiert und wird beim beenden von main zerstört. Falls jetzt clog im Destruktor versucht auf seinen Buffer zugreifen (z.B. mit einem flush), existiert der schon lange nicht mehr.
-
Der Thread ist aber uralt ...
DJohn@work schrieb:
Einen Plan habe ich nicht aber eine Vermutung.
clog ist ein statisches Objekt und der Destruktor wird erst aufgerufen, wenn die Funktion main schon beendet ist. logBuf ist dagegen innerhalb der Funktion main definiert und wird beim beenden von main zerstört. Falls jetzt clog im Destruktor versucht auf seinen Buffer zugreifen (z.B. mit einem flush), existiert der schon lange nicht mehr.Das würde ich auch vermuten.
@FridgeStone,
Dasclose
sollte nicht nötig sein, da dies im Destruktor vonfilebuf
automatisch aufgerufen wird.
http://www.cplusplus.com/reference/iostream/filebuf/~filebuf/Allerdings sollte man die beiden
streambuf
Objekte von denstd::clog
undstd::cerr
Streams auf 0 setzen:#include <fstream> #include <iostream> int main() { std::filebuf logBuf; std::filebuf errBuf; logBuf.open("log.txt", std::ios::out); errBuf.open("err.txt", std::ios::out); std::clog.rdbuf(&logBuf); std::cerr.rdbuf(&errBuf); std::cout << "Hallo!" << std::endl; std::clog << "Meldung!" << std::endl; std::cerr << "Fehler!" << std::endl; std::clog.rdbuf(0); // <- std::cerr.rdbuf(0); // <- return 0; }
Damit sollte auch der Segmentation Fault verschwinden.
Der Code war halt nur zur Veranschaulichung gedacht, nicht als lauffähiges Beispiel
Grüssli