2009-08-20 3 views
4

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?

+1

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. –

+1

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

Antwort

13

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.

+0

Ja, das ist genau das, wofür Makros da sind !! – Newtopian

+6

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

+2

Ja, wird es. Nichts kommt umsonst in dieser Welt. – sharptooth

1

Ich habe so etwas mit dem Präprozessor schon einmal gemacht.

#ifndef DEBUG 
#define debugPrint 
#endif 

im Wesentlichen, dass alle Debug-Linien

+1

Err, würde das nicht das gültige 'debugPrintf ("Hallo");' in das ziemlich ungültige "(" hallo "); ' ? – paxdiablo

+1

@Pax, das ist absolut gültig. – strager

+1

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

7

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.

+2

Wird garantiert, dass der Funktionsparameter nicht ausgewertet wird? – sharptooth

+0

Dies hilft nicht bei der anderen Anforderung (dass, wenn es Code gibt, der ausgewertet werden muss, um wtvr zu berechnen, auch nicht erzeugt wird) –

+3

@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

1

#ifdef _DEBUG 
#define debugPrint(x) _debugPrint(x) 
void _debugPrint(int foo) { 
    // debugPrint implementation 
} 
#else 
#define debugPrint(x) 
#endif 
2

@ 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

Verwandte Themen