2008-08-26 7 views
10

El TRACE macro se puede utilizar para enviar mensajes de diagnóstico al depurador cuando el código se compila en el modo Depurar. Necesito los mismos mensajes en el modo Release. ¿Hay una manera de lograr esto?¿Cómo habilitar la macro TRACE en el modo de lanzamiento?

(por favor, no pierda su tiempo a discutir por qué no debería usar TRACE en modo de lanzamiento :-)

+0

Para ATL proyectos Tengo una clase gratuita que redefine macros y mapas 'ATLTRACE' a 'OutputDebugString' (incluida la aceptación de una cantidad flexible de parámetros): http://alax.info/blog/tag/outputdebugstring –

Respuesta

8

En realidad, la macro TRACE es mucho más flexible que OutputDebugString. Se necesita una cadena de formato de estilo printf() y una lista de parámetros, mientras que OutputDebugString simplemente toma una sola cadena. Con el fin de implementar la funcionalidad TRACE completa en modo de lanzamiento que tiene que hacer algo como esto:

void trace(const char* format, ...) 
{ 
    char buffer[1000]; 

    va_list argptr; 
    va_start(argptr, format); 
    wvsprintf(buffer, format, argptr); 
    va_end(argptr); 

    OutputDebugString(buffer); 
} 
+4

Sé que esto es solo un ejemplo, pero existe un enorme potencial de desbordamiento de búfer en este ejemplo, tal como está. – Aardvark

1

En MFC, TRACE se define como ATLTRACE. Y en modo de lanzamiento que se define como:

#define ATLTRACE   __noop 

Por lo tanto, el uso de la fuera de la caja TRACE de MFC, usted realmente no ser capaz de leer cualquier texto TRACE, ya que ni siquiera se puede escribir fuera. En su lugar, podría escribir su propia función TRACE y luego volver a definir la macro TRACE. Se podría hacer algo como esto:

void MyTrace(const CString& text) 
{ 
    ::OutputDebugString(text); // Outputs to console, same as regular TRACE 
    // TODO: Do whatever output you need here. Write to event log/write to text file/write to pipe etc. 
} 
4

Hace algunos años que tenía una funcionalidad similar, así que improvisó el siguiente código. Simplemente guárdelo en un archivo, p. rtrace.h, inclúyalo al final de su stdafx.hy añada _RTRACE al modo de lanzamiento que define el preprocesador.

Tal vez alguien va a encontrar un uso para él :-)

John

 
#pragma once 

//------------------------------------------------------------------------------------------------ 
// 
// Author: John Cullen 
// Date:  2006/04/12 
// Based On: MSDN examples for variable argument lists and ATL implementation of TRACE. 
// 
// Description: Allows the use of TRACE statements in RELEASE builds, by overriding the 
// TRACE macro definition and redefining in terms of the RTRACE class and overloaded 
// operator(). Trace output is generated by calling OutputDebugString() directly. 
// 
// 
// Usage: Add to the end of stdafx.h and add _RTRACE to the preprocessor defines (typically 
//   for RELEASE builds, although the flag will be ignored for DEBUG builds. 
// 
//------------------------------------------------------------------------------------------------ 

#ifdef _DEBUG 

// NL defined as a shortcut for writing FTRACE(_T("\n")); for example, instead write FTRACE(NL); 
#define NL _T("\n") 
#define LTRACE TRACE(_T("%s(%d): "), __FILE__, __LINE__); TRACE 
#define FTRACE TRACE(_T("%s(%d): %s: "), __FILE__, __LINE__, __FUNCTION__); TRACE 

#else // _DEBUG 

#ifdef _RTRACE 
#undef TRACE 
#define TRACE RTRACE() 
#define LTRACE RTRACE(__FILE__, __LINE__) 
#define FTRACE RTRACE(__FILE__, __LINE__, __FUNCTION__) 
#define NL _T("\n") 

class RTRACE 
{ 
public: 
    // default constructor, no params 
    RTRACE(void) : m_pszFileName(NULL), m_nLineNo(0), m_pszFuncName(NULL) {}; 

    // overloaded constructor, filename and lineno 
    RTRACE(PCTSTR const pszFileName, int nLineNo) : 
     m_pszFileName(pszFileName), m_nLineNo(nLineNo), m_pszFuncName(NULL) {}; 

    // overloaded constructor, filename, lineno, and function name 
    RTRACE(PCTSTR const pszFileName, int nLineNo, PCTSTR const pszFuncName) : 
     m_pszFileName(pszFileName), m_nLineNo(nLineNo), m_pszFuncName(pszFuncName) {}; 

    virtual ~RTRACE(void) {}; 

    // no arguments passed, e.g. RTRACE()() 
    void operator()() const 
    { 
     // no arguments passed, just dump the file, line and function if requested 
     OutputFileAndLine(); 
     OutputFunction(); 
    } 

    // format string and parameters passed, e.g. RTRACE()(_T("%s\n"), someStringVar) 
    void operator()(const PTCHAR pszFmt, ...) const 
    { 
     // dump the file, line and function if requested, followed by the TRACE arguments 
     OutputFileAndLine(); 
     OutputFunction(); 

     // perform the standard TRACE output processing 
     va_list ptr; va_start(ptr, pszFmt); 
     INT len = _vsctprintf(pszFmt, ptr) + 1; 
     TCHAR* buffer = (PTCHAR) malloc(len * sizeof(TCHAR)); 
     _vstprintf(buffer, pszFmt, ptr); 
     OutputDebugString(buffer); 
     free(buffer); 
    } 

private: 
    // output the current file and line 
    inline void OutputFileAndLine() const 
    { 
     if (m_pszFileName && _tcslen(m_pszFileName) > 0) 
     { 
      INT len = _sctprintf(_T("%s(%d): "), m_pszFileName, m_nLineNo) + 1; 
      PTCHAR buffer = (PTCHAR) malloc(len * sizeof(TCHAR)); 
      _stprintf(buffer, _T("%s(%d): "), m_pszFileName, m_nLineNo); 
      OutputDebugString(buffer); 
      free(buffer); 
     } 
    } 

    // output the current function name 
    inline void OutputFunction() const 
    { 
     if (m_pszFuncName && _tcslen(m_pszFuncName) > 0) 
     { 
      INT len = _sctprintf(_T("%s: "), m_pszFuncName) + 1; 
      PTCHAR buffer = (PTCHAR) malloc(len * sizeof(TCHAR)); 
      _stprintf(buffer, _T("%s: "), m_pszFuncName); 
      OutputDebugString(buffer); 
      free(buffer); 
     } 
    } 

private: 
    PCTSTR const m_pszFuncName; 
    PCTSTR const m_pszFileName; 
    const int m_nLineNo; 
}; 

#endif // _RTRACE 

#endif // NDEBUG 

2

Es más simple código que tuve ver

#undef ATLTRACE 
#undef ATLTRACE2 

#define ATLTRACE2 CAtlTrace(__FILE__, __LINE__, __FUNCTION__) 
#define ATLTRACE ATLTRACE2 

ver http://alax.info/blog/1351

Cuestiones relacionadas