Как включить макрос ТРАССИРОВКИ в режиме выпуска?
Вопрос
Тот Самый Макрос ТРАССИРОВКИ может использоваться для вывода диагностических сообщений в отладчик при компиляции кода в Отлаживать режим.Мне нужны те же сообщения, что и в Освободить режим.Есть ли способ добиться этого?
(Пожалуйста, сделайте нет тратьте свое время на обсуждение того, почему я не должен использовать ТРАССИРОВКУ в режиме выпуска :-)
Решение
На самом деле, макрос ТРАССИРОВКИ намного более гибкий, чем OutputDebugString.Он принимает строку формата в стиле printf() и список параметров, тогда как OutputDebugString принимает только одну строку.Чтобы реализовать полную функциональность ТРАССИРОВКИ в режиме выпуска, вам нужно сделать что-то вроде этого:
void trace(const char* format, ...)
{
char buffer[1000];
va_list argptr;
va_start(argptr, format);
wvsprintf(buffer, format, argptr);
va_end(argptr);
OutputDebugString(buffer);
}
Другие советы
Несколько лет назад мне нужна была аналогичная функциональность, поэтому я собрал следующий код.Просто сохраните его в файл, напримерrtrace.h, включите его в конец вашего stdafx.h и добавьте _RTRACE в режим выпуска, определенный препроцессором.
Может быть, кто-нибудь найдет этому применение :-)
Джон
#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
ТРАССИРОВКА - это просто макрос для OutputDebugString Вывод строки.Таким образом, вы можете легко просто создать свой собственный макрос ТРАССИРОВКИ (или назвать его как-то по-другому), который вызовет OutputDebugString Вывод строки.
Это самый простой код, который я когда-либо видел
#undef ATLTRACE
#undef ATLTRACE2
#define ATLTRACE2 CAtlTrace(__FILE__, __LINE__, __FUNCTION__)
#define ATLTRACE ATLTRACE2
видишь http://alax.info/blog/1351
В MFC ТРАССИРОВКА определяется как ATLTRACE.И в режиме выпуска, который определяется как:
#define ATLTRACE __noop
Таким образом, используя готовую ТРАССИРОВКУ из MFC, вы фактически не сможете прочитать какой-либо текст трассировки, потому что он даже не будет записан.Вместо этого вы могли бы написать свою собственную функцию ТРАССИРОВКИ, а затем переопределить макрос ТРАССИРОВКИ.Вы могли бы сделать что-то вроде этого:
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.
}