Comment activer la macro TRACE en mode Release ?
Question
Le Macro TRACE peut être utilisé pour envoyer des messages de diagnostic au débogueur lorsque le code est compilé dans Déboguer mode.J'ai besoin des mêmes messages pendant mon séjour Libérer mode.Existe-t-il un moyen d'y parvenir ?
(Je vous en prie pas perdez votre temps à discuter des raisons pour lesquelles je ne devrais pas utiliser TRACE en mode Release :-)
La solution
En fait, la macro TRACE est beaucoup plus flexible que OutputDebugString.Il prend une chaîne de format de style printf() et une liste de paramètres alors que OutputDebugString ne prend qu'une seule chaîne.Afin d'implémenter toutes les fonctionnalités de TRACE en mode release, vous devez procéder comme suit :
void trace(const char* format, ...)
{
char buffer[1000];
va_list argptr;
va_start(argptr, format);
wvsprintf(buffer, format, argptr);
va_end(argptr);
OutputDebugString(buffer);
}
Autres conseils
Il y a quelques années, j'avais besoin de fonctionnalités similaires, j'ai donc bricolé le code suivant.Enregistrez-le simplement dans un fichier, par ex.rtrace.h, incluez-le à la fin de votre stdafx.h et ajoutez _RTRACE au mode de publication défini par le préprocesseur.
Peut-être que quelqu'un y trouvera une utilité :-)
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 n'est qu'une macro pour OutputDebugString.Vous pouvez donc facilement créer votre propre macro TRACE (ou l'appeler autrement) qui appellera OutputDebugString.
C'est tout simplement du code que j'ai vu
#undef ATLTRACE
#undef ATLTRACE2
#define ATLTRACE2 CAtlTrace(__FILE__, __LINE__, __FUNCTION__)
#define ATLTRACE ATLTRACE2
Dans MFC, TRACE est défini comme ATLTRACE.Et en mode release défini comme :
#define ATLTRACE __noop
Ainsi, en utilisant le TRACE prêt à l'emploi de MFC, vous ne pourrez réellement lire aucun texte TRACE, car il ne sera même pas écrit.Vous pouvez plutôt écrire votre propre fonction TRACE, puis redéfinir la macro TRACE.Vous pourriez faire quelque chose comme ceci :
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.
}