Domanda

IL macro TRACCIA può essere utilizzato per inviare messaggi diagnostici al debugger quando il codice viene compilato Debug modalità.Ho bisogno degli stessi messaggi mentre sono dentro Pubblicazione modalità.C'è un modo per raggiungere questo obiettivo?

(Per favore fallo non spreca il tuo tempo discutendo del motivo per cui non dovrei utilizzare TRACE in modalità di rilascio :-)

È stato utile?

Soluzione

In realtà, la macro TRACE è molto più flessibile di OutputDebugString.Richiede una stringa di formato in stile printf() e un elenco di parametri mentre OutputDebugString richiede solo una singola stringa.Per implementare la funzionalità TRACE completa in modalità di rilascio è necessario fare qualcosa del genere:

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

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

   OutputDebugString(buffer);
}

Altri suggerimenti

Qualche anno fa avevo bisogno di funzionalità simili, quindi ho messo insieme il seguente codice.Basta salvarlo in un file, ad es.rtrace.h, includilo alla fine di stdafx.h e aggiungi _RTRACE alla modalità di rilascio definita dal preprocessore.

Magari qualcuno gli troverà un utilizzo :-)

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

TRACE è solo una macro per OutputDebugString.Quindi puoi facilmente creare la tua macro TRACE (o chiamarla in altro modo) che chiamerà OutputDebugString.

È semplicemente il codice che avevo visto

#undef ATLTRACE
#undef ATLTRACE2

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

Vederehttp://alax.info/blog/1351

In MFC, TRACE è definito come ATLTRACE.E nella modalità di rilascio definita come:

#define ATLTRACE            __noop

Quindi, utilizzando TRACE pronto all'uso di MFC, non sarai effettivamente in grado di leggere alcun testo TRACE, perché non verrà nemmeno scritto.Potresti invece scrivere la tua funzione TRACE, quindi ridefinire la macro TRACE.Potresti fare qualcosa del genere:

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.
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top