VS-Tipps&Tricks: Einfache Debug-Ausgabe mit TRACE auch in der Release Version
Wer wollte nicht schon immer mal gerne TRACE (Debug)-Ausgaben in seinem Release Programm haben ohne dafür überall OutputDebugString reinschreiben zu müssen.
Die nachfolgene kleine Klasse macht es möglich, den gewohnten Syntax des MFC TRACE Makros zu verwenden und direkt auf die Debugausgabe umzuleiten:
// CTraceToOutputDebugString // Is a nice replacment class for TRACE // Easy to use with: // #undef TRACE // #define TRACE CTraceToOutputDebugString() class CTraceToOutputDebugString { public: // Non Unicode output helper void operator()(PCSTR pszFormat, ...) { va_list ptr; va_start(ptr, pszFormat); TraceV(pszFormat,ptr); va_end(ptr); } // Unicode output helper void operator()(PCWSTR pszFormat, ...) { va_list ptr; va_start(ptr, pszFormat); TraceV(pszFormat,ptr); va_end(ptr); } private: // Non Unicode output helper void TraceV(PCSTR pszFormat, va_list args) { // Format the output buffer char szBuffer[1024]; _vsnprintf(szBuffer, _countof(szBuffer), pszFormat, args); OutputDebugStringA(szBuffer); } // Unicode output helper void TraceV(PCWSTR pszFormat, va_list args) { wchar_t szBuffer[1024]; _vsnwprintf(szBuffer, _countof(szBuffer), pszFormat, args); OutputDebugStringW(szBuffer); } };
Durch den obenstehenden Code kann man auch in einer Release Version Trace Ausgaben erzeugen und z.B. mit DebugView.exe (Sysinternals) sichtbar machen, ohne evtl. weitere Anpassungen vornehmen zu müssen:
// Activate my special tracer #undef TRACE #define TRACE CTraceToOutputDebugString() void Foo() { // Sometime usefull to see the output in a release version too TRACE(__FUNCTION__ " called at %d\n", GetTickCount()); }
9 Kommentare zu “VS-Tipps&Tricks: Einfache Debug-Ausgabe mit TRACE auch in der Release Version”
Link für diesen Beitrag | RSS-Feed zu diesem Beitrag
Hinterlassen sie einen Kommentar:
Beachten sie bitte, dass Kommentare evtl. nicht sofort hier erscheinen. Die Kommentare werden zur Moderation an den Webmaster gesendet. Es kann also etwas dauern, bis Ihr Kommentar hier veröffentlicht wird!
on Mo 10 Aug 2009 um 15:05 #
Torsten
Jep. Vor Jahren schon geschrieben und läuft tadellos…
Zweiter Tipp, man kann es auch noch erweitern und gleich in ein Logfile ausgeben. Dazu nutze ich es dann auch noch, dazu dann noch verschlüsselt und in einem eigenen Format, damit ich es dann später mit einem Programm mir einfach anzeigen und auch nach Nachrichten filtern kann.
Das ganze läuft in einem extra Thread bei mir. Aus den eigentlichen Arbeitsthreads kommen alle Trace Sachen in meiner Log.dll an. Diese sammelt die Nachrichten und wenn Zeit ist, schreibt sie sie parallel mit raus. Damit verliert man recht wenig Zeit.
Im Laufe der Jahre hat mich allerdings auch ein was immer mehr genervt.
Nämlich das man es nicht wie einen Stream beschreiben kann und damit einfacher und C++ konformer in sein Programm mit einbauen kann.
Irgendwann muss ich mir die Arbeit wohl mal noch machen und das alles noch einmal dahin mit umschreiben, so das man beides kann.
on Mo 10 Aug 2009 um 17:12 #
edgar
Ja Martin, nettes Beispiel.
Das würde ich aber trotzdem so nicht benutzen wollen.
_vsnprintf() frisst zuviel(unnötige) performance bei abgeschaltetem debug output.
Da würde sich ein vorheriger Blick auf “DBWinMutex” lohnen.
on Di 11 Aug 2009 um 07:47 #
Torsten
Hm, Kurze Frage: Was hat _vsnprintf mit dem Debug Output zu tun?
Also nach meiner Meinung läuft das nicht langsamer, egal was ein oder ausgeschaltet ist.
on Di 11 Aug 2009 um 15:20 #
edgar
Nun Torsten, es wird ja erst in OutputDebugString() festgestellt,
ob überhaupt ein Trace gewünscht wird.
Die Codesequenz davor wird also immer ausgeführt, ob es notwendig ist oder nicht.
on Di 11 Aug 2009 um 19:52 #
Torsten Schröder
Das seh ich nich so edgar, das liese sich recht schnell per ifdef komplett aus dem Programm entfernen, und ein leeres define auf Trace wird wegoptimiert. Alternativ gänge auch ein zur Laufzeit gesetztes Bool, wenn man es ein-/ausschaltbar haben möchte.
on Di 11 Aug 2009 um 22:24 #
edgar
Richtig Torsten. Dein Alternativvorschlag kommt der Intention meines ersten posts schon sehr nahe.
Ich meinte einfach: Es fehlt noch etwas Optimierung.
on Mi 12 Aug 2009 um 07:58 #
Torsten
Dein DBWinMutex Vorschlag fand ich auch nicht so schlecht, allerdings bin ich eher der Typ der das dann lieber selber schreibt als irgendwas fertiges zu nehmen.
Das auch der Grund weshalb mein Zeug nach 10 Jahren auch so stark angewachsen ist.
on Mi 12 Aug 2009 um 09:20 #
Torsten
Ach wenn wir grad an kleinen Hilfsmakros sind
Beispiel:
#pragma todo(“sonderbehandlung ja/nein”)
ergibt
1>DlgFz.cpp
1>.\dlgs\DlgFz.cpp(604) : TODO : “sonderbehandlung ja/nein”
PS: falls ich code zeug falsch gemacht hab, bitte nacharbeiten
on Mi 12 Aug 2009 um 09:30 #
Martin Richter
Man kann den Code optimieren, indem man eine zusätzliche statische Variable mit diesem Code lädt und die entsprechenden Ausabefunktionen nur zulässt wenn die entsprechende statische Variable true ist.