Unterschied zwischen cerr und cout



  • Dravere schrieb:

    ...
    Viel wichtiger dabei anzumerken ist wohl, dass stdout und stderr 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


  • Administrator

    std::cerr und std::clog gehen per Default nach stderr . 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


  • Administrator

    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 Protokoll

    Grüssli



  • Das Beispielprogramm compiliert besser wenn es so aussieht:
    rdbuf( & ... ) statt rdbuf( ... )

    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.


  • Administrator

    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,
    Das close sollte nicht nötig sein, da dies im Destruktor von filebuf automatisch aufgerufen wird.
    http://www.cplusplus.com/reference/iostream/filebuf/~filebuf/

    Allerdings sollte man die beiden streambuf Objekte von den std::clog und std::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


Anmelden zum Antworten