Angenommen, ich habe eine C++ - Funktion debugPrint (int foo). Wie kann ich das am besten aus Release-Builds entfernen? Ich möchte nicht jeden Aufruf von debugPrint mit #ifdefs umgeben, da es sehr zeitaufwändig wäre. Auf der anderen Seite möchte ich 100% sicher sein, dass der Compiler alle Aufrufe dieser Funktion und die Funktion selbst von Release-Builds entfernt. Das Strippen sollte auch passieren, wenn es mit einem Parameter aufgerufen wird, der aus einem Funktionsaufruf resultiert. Z. B. debugPrint (getFoo()) ;. In diesem Fall möchte ich auch den Aufruf von getFoo() entfernen. Ich verstehe, dass Funktion Inlining eine Option sein könnte, aber Inlining wird nicht garantiert, unterstützt zu werden.Wie kann Debug-Code während der Kompilierzeit in C++ entfernt werden?
Antwort
Verwenden conditinal Kompilierung und ein Makro:
#ifdef _DEBUG
#define LOG(x) debugPrint(x)
#else
#define LOG(x)
#endif
definieren _DEBUG
für das Debug-Build und es nicht für das Release-Build definieren. Jetzt in Version bauen jedes
LOG(blahbhahblah);
wird in eine leere Zeichenfolge erweitert werden - auch die Parameter werden nicht ausgewertet und wird nicht in den ausgesandten Code enthalten sein.
Sie können ein beliebiges bereits vorhandenes Präprozessorsymbol verwenden, das im Debug-Build definiert ist und nicht in Release definiert ist, anstatt _DEBUG
.
Ja, das ist genau das, wofür Makros da sind !! – Newtopian
Dies ist gefährlich und fehleranfällig. 'int x = 0; LOG (x + = 2); use (x); 'verhält sich anders, wenn" release "oder" debug "aktiviert ist. – LiraNuna
Ja, wird es. Nichts kommt umsonst in dieser Welt. – sharptooth
Ich habe so etwas mit dem Präprozessor schon einmal gemacht.
#ifndef DEBUG
#define debugPrint
#endif
im Wesentlichen, dass alle Debug-Linien
Err, würde das nicht das gültige 'debugPrintf ("Hallo");' in das ziemlich ungültige "(" hallo "); ' ? – paxdiablo
@Pax, das ist absolut gültig. – strager
Aber eine, die wahrscheinlich eine Warnung auslöst. '(void) (" Hallo ") scheint passender. Es ist jedoch falsch: debugPrint (GetFoo()) wird immer noch GetFoo() mit diesem Makro aufrufen, was explizit nicht gefordert wurde. – MSalters
Sprechen Sie die Funktion Inline entfernen, und innerhalb der Funktion haben die # ifdef ist, wie folgt aus:
inline void debugPrint(whatever_t wtvr)
{
#ifdef DEBUG
Logger::log(wtvr);
#endif
}
Auf diese Weise der Optimierer wird der Streifen leere Funktion, während der Code sauber bleibt.
Wird garantiert, dass der Funktionsparameter nicht ausgewertet wird? – sharptooth
Dies hilft nicht bei der anderen Anforderung (dass, wenn es Code gibt, der ausgewertet werden muss, um wtvr zu berechnen, auch nicht erzeugt wird) –
@sharptooth, Sie müssen mit dieser Lösung ausgewertet werden. Wenn jedoch die Bewertung die Funktionsweise des Programms ändert (dh die Nebeneffekte), besteht das Problem, dass die Aufrufe der Protokollfunktion mehr bewirken können als nur die Protokollierung. – strager
#ifdef _DEBUG
#define debugPrint(x) _debugPrint(x)
void _debugPrint(int foo) {
// debugPrint implementation
}
#else
#define debugPrint(x)
#endif
@ sharptooths Antwort ist gut. Eine kleine Veränderung, die ich normalerweise, aber machen, ist das Debuggen zu deaktivieren, wenn das NDEBUG
Makro nicht definiert, eher als wenn ein Debug-Makro ist definiert:
#ifndef NDEBUG
#define LOG(x) debugPrint(x)
#else
#define LOG(x)
#endif
Wenn das NDEBUG
Makro definiert ist, C assert
s, die ich eher dazu nutze, Dinge wie Vorbedingungen und Nachbedingungen zu behaupten oder gar das Ergebnis komplexer Logik zu verdeutlichen, falle auch aus der Kompilation heraus. Es ist ein Standardmakro für "no debugging". Und das Makro NDEBUG
sollte bereits in Release-Builds definiert sein.
See: http://www.opengroup.org/onlinepubs/009695399/functions/assert.html
- 1. Wie berechnet man Strukturauffüllung in C++ 11 während der Kompilierzeit?
- 2. Wie wechsle ich während der Kompilierzeit Typen?
- 3. Ermitteln von Compiler-Versionen während der Kompilierzeit
- 4. std :: array Klassenmitglied während der Kompilierzeit gesetzt?
- 5. Kann eine C-Variable während der Ausführung eines Programms jederzeit gelöscht oder entfernt werden?
- 6. Kann der Fließkomma-Rundungsmodus zur Kompilierzeit in Rust eingestellt werden?
- 7. Kann eine Datei zur Kompilierzeit gelesen werden?
- 8. Kompilierzeit und Laufzeitcasting C#
- 9. Kompilierzeit Typbestimmung in C++
- 10. C++: Kann die virtuelle Vererbung zur Kompilierzeit erkannt werden?
- 11. Kompilierzeit-Assertionen in C++?
- 12. Wie kann der Fokus von einem einzelnen Steuerelement entfernt werden?
- 13. c/C++ Kompilierzeit "Kompatibilitäts" check
- 14. Wie ein If zur Kompilierzeit in C++
- 15. Wie kann die Sammlung "Gruppe" entfernt werden?
- 16. Maximaler Speicher, der dynamisch zugeordnet werden kann und zur Kompilierzeit in C++
- 17. Kompilierzeit Fehler: 'Knoten * (Int)' kann nicht in 'Knoten *' konvertiert werden
- 18. Ist es möglich, benutzerdefinierte Attribute in C# während der Kompilierzeit abzufragen (keine Laufzeit)
- 19. C++ - Kompilierzeit Bignum-Bibliothek
- 20. EventListener kann nicht entfernt werden
- 21. Wie kann der von C/C++/Java verwendete Speicher während der Ausführung gemessen werden?
- 22. Padding in UITextView kann nicht entfernt werden
- 23. C++ Kompilierzeit Bitmaske Addition
- 24. Knoten in Nokogiri kann nicht entfernt werden
- 25. Wie können Trennzeichen ("") in der .txt-Datei entfernt werden?
- 26. Wie injiziere ich C# -Code zur Kompilierzeit?
- 27. Ordner kann nicht mit CMD entfernt werden
- 28. Kann Speicher für Referenzen innerhalb einer C++ - Klasse entfernt werden?
- 29. Überprüfung der C-Array-Ausrichtung zur Kompilierzeit
- 30. Wie kann Leerraum in einer mehrzeiligen HTML-Anordnung entfernt werden?
Der einzige Weg, 'getFoo()' in 'debugPrint (getFoo())' zu beseitigen Makro zu verwenden ist. Das führt aber dazu, dass sich das Programm in Debug- und Release-Konfigurationen anders verhält. Das ist wirklich gefährlich. –
Es ist gefährlich, wenn getFoo() eine andere versteckte Logik hat, als den Wert einer Variablen zu erhalten. Aber das ist eine schlechte Codierung. – juvenis