Несколько лет назад мне понадобилась похожая функциональность, поэтому я собрал следующий код. Просто сохраните его в файл, например, rtrace.h, включите его в конец вашего stdafx.h и добавьте _RTRACE в режим выпуска, который определяет препроцессор.
Может быть, кто-то найдет для него применение: -)
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