2009-01-16 17 views

Odpowiedz

7

_RPTn działa świetnie, ale nie tak wygodnie. Here is some code, który odtwarza instrukcję MFC TRACE jako funkcję dopuszczającą zmienną liczbę argumentów. Dodaje również makro TraceEx, które przedkłada plik źródłowy i numer wiersza, dzięki czemu można kliknąć z powrotem na lokalizację instrukcji.

Aktualizacja: Oryginalny kod w CodeGuru nie zostałby skompilowany dla mnie w trybie Release, więc zmieniłem sposób, w jaki instrukcje TRACE są usuwane do trybu Release. Oto moje pełne źródło, które umieściłem w Trace.h. Dzięki Thomas Rizos dla oryginalnego:

// TRACE macro for win32 
#ifndef __TRACE_H__850CE873 
#define __TRACE_H__850CE873 

#include <crtdbg.h> 
#include <stdarg.h> 
#include <stdio.h> 
#include <string.h> 

#ifdef _DEBUG 
#define TRACEMAXSTRING 1024 

char szBuffer[TRACEMAXSTRING]; 
inline void TRACE(const char* format,...) 
{ 
    va_list args; 
    va_start(args,format); 
    int nBuf; 
    nBuf = _vsnprintf(szBuffer, 
        TRACEMAXSTRING, 
        format, 
        args); 
    va_end(args); 

    _RPT0(_CRT_WARN,szBuffer); 
} 
#define TRACEF _snprintf(szBuffer,TRACEMAXSTRING,"%s(%d): ", \ 
       &strrchr(__FILE__,'\\')[1],__LINE__); \ 
       _RPT0(_CRT_WARN,szBuffer); \ 
       TRACE 
#else 
// Remove for release mode 
#define TRACE ((void)0) 
#define TRACEF ((void)0) 
#endif 

#endif // __TRACE_H__850CE873 
+0

Fajnie, to przydatny fragment. –

+0

szBuffer nie powinien być globalny, jeśli używasz TRACE w więcej niż jednym wątku – Anders

+0

dobry punkt - Myślę, że jeśli po prostu przesunę deklarację wewnątrz funkcji TRACE, to złamie się makro TRACEF - czy to prawda? – jacobsee

3

Od docs MSDN Macros for Reporting:

Można użyć _RPTn i makra _RPTFn, zdefiniowanego w CRTDBG.H, aby zastąpić użycie printf do debugowania. Te makra automatycznie znikają w kompilacji wydania, gdy _DEBUG nie jest zdefiniowany, więc nie ma potrzeby zamykania ich w #ifdefs.

3

Istnieje również OutputDebugString. Jednak nie zostanie to usunięte podczas kompilowania wydania.

1

Okazało się, że za pomocą _RPT() makro będzie również działać z plikiem źródłowym C w Visual Studio 2005. Ten artykuł Debugging with Visual Studio 2005/2008: Logging and Tracing zawiera przegląd TRACE, _RPT i innego rodzaju rejestrowania makra.

wygenerować linię do pliku dziennika o nazwie ASSRTLOG który zawiera dzienniki i pisząc dziennik do pliku, ja też zrobić następującą linię kodu źródłowego:

_RPT1(_CRT_WARN, "ASSRTLOG: %s", szLog1); 

Linia ta stawia ten sam dziennik, który przechodzi do pliku dziennika w oknie wyjściowym IDE Visual Studio 2005.

Może zainteresuje Cię mechanika stojąca za podejściem, którego używamy do rejestrowania. Mamy funkcję PifLogAbort(), która przyjmuje serię argumentów, które są następnie wykorzystywane do generowania dziennika. Te argumenty zawierają nazwę pliku, w którym generowany jest dziennik wraz z numerem wiersza.Makro wygląda następująco:

#define NHPOS_ASSERT_TEXT(x, txt) if (!(x)) { PifLogAbort((UCHAR *) #x , (UCHAR *) __FILE__ , (UCHAR *) txt , __LINE__);} 

i prototyp funkcji dla PifLogAbort() wyglądać następująco:

PifLogNoAbort(UCHAR *lpCondition, UCHAR *lpFilename, UCHAR *lpFunctionname, ULONG ulLineNo) 

i wykorzystać makro będziemy wstawić linię:

NHPOS_ASSERT_TEXT(sBRetCode >= 0, "CliEtkTimeIn(): EtkTimeIn() returned error"); 

To, co zrobi to makro, to to, że jeśli kod powrotu jest mniejszy niż 0 (asercja nie powiedzie się), zostanie wygenerowany dziennik z dostarczonym tekstem. Dziennik zawiera warunek, który wygenerował dziennik wraz z nazwą pliku i numerem linii.

Funkcja PifLogAbort() generuje logi o określonej długości i traktuje plik wyjściowy jako bufor cykliczny. Dzienniki mają również znacznik czasu i daty.

W tych przypadkach, w których chcemy wygenerować tekst opisowy dynamicznie w czasie wykonywania, może zapewnić rzeczywistą wartość kodu błędu, możemy skorzystać z funkcji sprintf() z buforem jak w poniższej sekwencji kodu:

if (sErrorSave != STUB_BM_DOWN) { 
    char xBuff[128]; 
    sprintf(xBuff, "CstSendBMasterFH: CstComReadStatus() - 0x%x, sError = %d", usCstComReadStatus, CliMsg.sError); 
    NHPOS_ASSERT_TEXT((sErrorSave == STUB_BM_DOWN), xBuff); 
} 

Jeśli chcemy, aby dzienniki nie były generowane, musimy tylko przejść do pojedynczego pliku nagłówkowego, w którym zdefiniowane jest makro i zdefiniować je jako nic, a następnie przekompilować. Jednak stwierdziliśmy, że te dzienniki mogą być bardzo cenne podczas badania problemów w terenie i są szczególnie przydatne podczas testowania integracji.

2

wystarczy użyć mniej więcej tak (z pamięci, nie testowane na wszystkich ...)

#define TRACE(msg) {\ 
    std::ostringstream ss; \ 
    ss << msg << "\n"; \ 
    OutputDebugString(msg.str()); \ 
} 

I wtedy można pisać takie rzeczy jak: -

TRACE("MyClass::MyFunction returned " << value << " with data=" << some.data); 

można zawinąć że w niektóre #ifdefs do usunięcia go w wersji łatwo buduje.

+1

Troszkę poprawkę: 'OutputDebugString (ss.str(). C_str());' powinien być użyty zamiast 'OutputDebugString (msg.str());' – Apokal

0

Windows Events są potencjalnym zamiennikiem dla makr TRACE, w zależności od konkretnego scenariusza. Kod zostanie wkompilowany w konfiguracje Debug and Release. Śledzenie zdarzeń można dynamicznie włączać i wyłączać, wyświetlać w czasie rzeczywistym lub umieszczać na maszynie klienta w celu późniejszej diagnozy. Ślady można skorelować z informacjami śledzenia uzyskanymi również z innych części systemu operacyjnego.

Jeśli potrzebujesz tylko zrzutu informacji, ilekroć kod dociera do określonych punktów kontrolnych, wraz ze zmienną zawartością, śladami stosu lub nazwami dzwoniących, Visual Studio to Tracepoints jest nieinwazyjną opcją, aby to zrobić.

Powiązane problemy