macros, debug macros, werden sie wirklich entfernt?
-
Hallo,
ich habe ein kleines Programm geschrieben. Nun möchte ich mir gern zum testen bei den jeweiligen Funktionen Informationen ausgeben lassen. Derzeit habe ich in der Klasse eine Methode ->debug(...args). Dieser übergebe ich dann alle möglichen Informationen. Nun ist es so, das wenn ich diese Details nicht mehr möchte, ich in der Methode vorher ganz simpel prüfe "if (this->_debug == true)" und dann ggf. direkt abbreche.
Das führt aber dazu, das selbst wenn _debug false ist, die Dateien sehr groß werden und vor allem der Sprung zu debug(...args) dennoch erfolgt. Und auch alle Werte erst mal auf den stack gepackt werden.
Ich könnte jetzt überall so etwas wie
#ifdef DEBUG Klasse->debug("Was auch immer %s", "noch ein Text"); #endifmachen, was ich Persönlich aber sehr umständlich und unschön finde.
Jetzt meine Frage dazu, könnte ich nicht auch ein komplettes Macro definieren:#ifdef DEBUG #define DEBUG_MSG(msg, ... args); \ // weiterer code #else #define DEBUG_MSG(nothing); #endifund dann überall halt . DEBUG_MSG("Text: %s", "Test"); nutzen und würde der compiler wenn DEBUG aus ist alle diese Zeilen wirklich löschen?
mfg Spoocy
-
Das würde das machen, was du willst, mit der kleinen Klarstellung, dass der Compiler das nicht entfernen würde, sondern dass der Compiler es gar nicht erst zu Gesicht bekommt, weil der Präprozessor es längst entfernt hat, bevor der Compiler überhaupt dran kommt.
-
Ist das auch ein Weg den man so gehen sollte/kann ohne das alle schreien würden "um Gottes willen"?.
-
Hm, wenn man sich der potentiellen Probleme bewusst ist...
Finde http://www.drdobbs.com/cpp/a-highly-configurable-logging-framework/225700666 ganz interessant, insbesondere:
Preprocessor implemented logging often has side effects. For instance, if you want to call a function always and for debugging purpose you print its return value with the help of a logging macro like LOGGING(ret=f()) the function is only called if logging is active. If the macro is empty defined to disable logging, the function will never be called. Such Heisenbugs are hard to find.
-
Ich würde das eher in dieser Art lösen:
struct Klasse { #ifdef DEBUG void debug(const string& message) { cerr << message << "\n"; } #else void debug(const string& message) { } #endif };Das hat den Vorteil dass man sich weder den Code mit
#ifdefs zupflastern, noch überall Makros verwenden muss
(die besonders dann schnell zum Krampf werden wenn sie kurze, eingängliche Namen haben wie DEBUG_MSG und man in dem Projekt auch fremden Code einbindet ;)).Finnegan
-
Hier würde aber wieder das Problem entstehen das an den stellen wo ich dann
Klasse->debug("Irgend ein text: %s", andereKlasse->functionsaufruf());
aufrufe, zum einen "andereKlasse->functionsaufruf()" ausgeführt wird (was ich dann gar nicht mehr möchte) und zum anderem der spring in die leere debug Funktion dennoch erfolgt oder?
Wenn Debug ausgeschaltet ist, soll es so sein als hätte ich nirgendwo irgend einen Debugtext / Funktion aufgerufen.
-
Angelehnt an das
KdPrintMakro des Windows DDK:namespace DebugDetail { inline void Nothing() {} } // namespace DebugDetail #ifndef NDEBUG #define MY_DEBUG_PRINTF(x) ::std::printf x #else #define MY_DEBUG_PRINTF(x) ::DebugDetail::Nothing() #endif //-------------------------------------------------- void SomeFunction() { MY_DEBUG_PRINTF(("Formatstring %d", 123)); }Iostream-Style geht auch, da braucht man aber ein wesentlich aufwendigeres Makro.