Debug-Consolenausgabe -> Macro oder Funktion



  • Moinmoin

    Ich bin die Debug-Consolenausgabe mit C++ nun leid. Jedesmal zu schreiben:

    #ifdef _DEBUG_
        std::cout << "Blabla!" << std::endl;
    #endif
    

    Also will ich eine Funtion oder ein Macro machen:

    #define writeDbgLn(text) { #ifdef _DEBUG_ /
        std::cout << text << std::endl; /
    #endif }
    
    //oder
    
    void writeDbgLn( const char* text )
    {
    #ifdef _DEBUG_
        std::cout << text << std::endl;
    #endif
    }
    
    //Aufruf
    writeDbgLn("Blabla");
    

    Ist das gut, Blödsinn oder einfach unnötig?



  • Makro machen! Dann haste keine Laufzeitkosten in der Release-Version.



  • dürfte eine leere funktion im release nicht wegoptimiert werden?



  • Ja, sach mal. Wär dann ja besser mit Funktion, da Typsicher.



  • Hi!

    Machs so:

    #ifdef _DEBUG_
    	inline void writeDbgLn( const char *text )
    	{
    		std::cout << text << std::endl;
    	}
    #else
    	#define writeDbgLn
    #endif
    

    grüße



  • ... schrieb:

    dürfte eine leere funktion im release nicht wegoptimiert werden?

    Nein! Der Compiler kann ja nicht wissen, ob sie aufgerufen wird.
    (z.B. über ".c"-Dateigrenzen hinweg)



  • David_pb schrieb:

    #ifdef _DEBUG_
    	inline void writeDbgLn( const char *text )
    	{
    		std::cout << text << std::endl;
    	}
    #else
    	#define writeDbgLn
    #endif
    

    Kenne mich nicht mehr so gut mit Präprozessor-Anweisungen aus,
    aber kann das überhaupt funktionieren?

    Wenn Debug nicht gesetzt ist, würde doch aus

    writeDbgLn("Ich will nicht ausgegeben werden :-(");
    

    doch

    ("Ich will nicht ausgegeben werden :-(");
    

    Meckert dann nicht der Compiler über den String in einem
    Klammernpaar?

    Ohne Klammern ist es allerdings syntaktisch korrekt, für den
    Compiler halt eine genause sinnentfreite, aber erlaubte Anweisung wie

    42;
    


  • Uuuppss!

    Nehme die Frage zurück!

    Ein Ausdruck darf ja beliebig oft geklammer werden.
    🙄



  • ... schrieb:

    dürfte eine leere funktion im release nicht wegoptimiert werden?

    die funktion ist nicht das problem. das problem ist die auswertung der parameter und die geschieht bei der funktion aber nicht beim makro.

    Ja, sach mal. Wär dann ja besser mit Funktion, da Typsicher.

    nö. typfehlermeldungen gibts auch bei falschem makroaufruf, denn der tut ja dann eh in typsichere funktionen umleiten.

    #ifdef _DEBUG_
        inline void writeDbgLn( const char *text )
        {
            std::cout << text << std::endl;
        }
    #else
        #define writeDbgLn
    #endif
    

    freiwilliges wegwerfen von makrmacht?

    #ifdef _DEBUG_
    #define writeDbgLn(MSG) std::cout << (MSG) << std::endl;
    #else
    #define writeDbgLn(MSG)
    #endif
    

    und schon klappts auch mit

    for(int i=0;i<100;++i){
    writeDbgLn("teste datei nummer "<<i<<" auf vollstaendigkeit")
    ...
    }
    


  • Nö, wenn man die leere Funktion in nem Header hat (->inline), dann schmeißt nen Compiler die normalerweise raus.
    Ich hab bis jetzt aber auch immer nen Makro verwendet.



  • volkard schrieb:

    #ifdef _DEBUG_
    #define writeDbgLn(MSG) std::cout << (MSG) << std::endl;
    #else
    #define writeDbgLn(MSG)
    #endif
    

    Stimmt! Diese Variante verhindert das Berechnen des geklammerten
    Ausdrucks, daß Nebeneffekte haben könnte.

    Erweiterte Frage:

    Kann man das auch mit Funktionen machen, die eine variable
    Parameteranzahl haben? (va_list und Co)



  • Javaner schrieb:

    Kann man das auch mit Funktionen machen, die eine variable
    Parameteranzahl haben? (va_list und Co)

    es gibt keine makros mit variabler patrameteranzahl.
    willste writeDbgLn mit va_list machen, dann wie printf. verlierst aber zur strafw alle typinformationen und kopiersemantik und so, was man von c++ gewohnt ist, was die sache berauschend unbrauchbar macht.



  • volkard schrieb:

    was die sache berauschend unbrauchbar macht.

    Nicht sehr ermutigend! 😞
    😃



  • volkard schrieb:

    freiwilliges wegwerfen von makrmacht?

    Makromacht? Die von dir erwähnte Macht würde mich mal interessieren.

    grüße



  • David_pb schrieb:

    Makromacht? Die von dir erwähnte Macht würde mich mal interessieren.

    writeDbgLn("teste datei nummer "<<i<<" auf vollstaendigkeit")
    

    und da hab ich noch nicht __FILE__ und __LINE__ verwendet.



  • Und in vc kann man noch das sehr nützliche define __FUNCTION__ verwenden.
    Außerdem gibts noch __TIMESTAMP__, dass das Built-Datum beinhaltet.



  • Ich möchte mal anmerken, dass es unter Umständen auch mal nützlich sein kann, die Debug Debug ausgabe zur laufzeit einschalten zu können.

    Wenn du dein Programm ausgeliefert hast und dein Kunde hat ein Problem, sagst du ihm zum Beispiel einfach einen Kommandozeilenparameter, der das Debuggen aktiviert und du kannst von ihm schonmal zu dem Fehlerreport eine Logdatei bekommen, ohne ihm extra eine Debug version zu schicken.

    Du kannst ja immernoch einen Macro schreiben, der dir zusätztliche Informationen mit __FILE__ und __LINE__ einfügt.



  • ProgChild schrieb:

    Ich möchte mal anmerken, dass es unter Umständen auch mal nützlich sein kann, die Debug Debug ausgabe zur laufzeit einschalten zu können.

    ist mir zu teuer.

    Wenn du dein Programm ausgeliefert hast und dein Kunde hat ein Problem, sagst du ihm zum Beispiel einfach einen Kommandozeilenparameter, der das Debuggen aktiviert und du kannst von ihm schonmal zu dem Fehlerreport eine Logdatei bekommen, ohne ihm extra eine Debug version zu schicken.

    ok, ich muß ihm ne log-version schicken.

    Du kannst ja immernoch einen Macro schreiben, der dir zusätztliche Informationen mit __FILE__ und __LINE__ einfügt.

    ich kann auch das makro mit ner laufzeitabfrage versehen.



  • ProgChild schrieb:

    Ich möchte mal anmerken, dass es unter Umständen auch mal nützlich sein kann, die Debug Debug ausgabe zur laufzeit einschalten zu können.

    Dann würde ich lieber 2 Debug Ausgaben verwenden. Eine statische, die wirklich nur im Debug Build greift, und eine dynamische, die immer greift.

    ProgChild schrieb:

    Wenn du dein Programm ausgeliefert hast und dein Kunde hat ein Problem, sagst du ihm zum Beispiel einfach einen Kommandozeilenparameter, der das Debuggen aktiviert und du kannst von ihm schonmal zu dem Fehlerreport eine Logdatei bekommen, ohne ihm extra eine Debug version zu schicken.

    Oder man liefert den Debug Build gleich von Anfang an mit. 🙂



  • Mein Logging-System ist von der Build-Art unabhängig was auch ganz gut ist.
    Es gibt drei Level, gar kein logging, etwas und viel. So kann ich in jedem Build einstellen wieviele Informationen ich haben möchte.
    Und dass man ein Release-Build genauso gründlich testen muss wie ein Debug-Build sollte jedem einleuchten.

    Dass man auch in der Endversion logging optional einschalten kann finde ich prinzipiell ne gute Sache und werde ggf. das ganze nochmal ändern, so dass wenigstens ein wenig logging in der endversion möglich ist.
    Hab zu Beginn schon darüber nachgedacht und bei den Makros lässt es sich ja sehr leicht machen, statt dem Funktionsaufruf einfach noch nen if-block außenrum.


Log in to reply