TRACE 宏可用于在调试模式下编译代码时向调试器输出诊断消息。在发布模式下我需要相同的消息。有没有办法做到这一点?
(请不要浪费时间讨论为什么我不应该在发布模式下使用 TRACE :-)
实际上,TRACE 宏比 OutputDebugString 灵活得多。它需要一个 printf() 样式的格式字符串和参数列表,而 OutputDebugString 只需要一个字符串。为了在发布模式下实现完整的 TRACE 功能,您需要执行以下操作:
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 一次
//------------------------------------------------ ------------------------------------------------
//
// 作者:约翰·卡伦
// 日期:2006/04/12
// 基于:变量参数列表的 MSDN 示例和 TRACE 的 ATL 实现。
//
// 描述:允许在 RELEASE 构建中使用 TRACE 语句,通过覆盖
// 根据 RTRACE 类和重载的 TRACE 宏定义和重新定义
// 操作员 ()。通过直接调用 OutputDebugString() 生成跟踪输出。
//
//
// 用法:添加到 stdafx.h 的末尾,并将 _RTRACE 添加到预处理器定义中(通常
// 对于 RELEASE 构建,尽管对于 DEBUG 构建,该标志将被忽略。
//
//------------------------------------------------ ------------------------------------------------
#ifdef _DEBUG
// NL 定义为编写 FTRACE(_T("\n")); 的快捷方式 例如,改为写 FTRACE(NL);
#define NL _T("\n")
#define LTRACE TRACE(_T("%s(%d): "), __FILE__, __LINE__); 痕迹
#define FTRACE TRACE(_T("%s(%d): %s: "), __FILE__, __LINE__, __FUNCTION__); 痕迹
#else // _DEBUG
#ifdef _RTRACE
#undef 追踪
#define TRACE RTRACE()
#define LTRACE RTRACE(__FILE__, __LINE__)
#define FTRACE RTRACE(__FILE__, __LINE__, __FUNCTION__)
#define NL _T("\n")
RTRACE 类
{
上市:
// 默认构造函数,无参数
RTRACE(void) : m_pszFileName( NULL ), m_nLineNo( 0 ), m_pszFuncName( NULL ) {};
// 重载构造函数、文件名和行号
RTRACE(PCTSTR const pszFileName,int nLineNo):
m_pszFileName(pszFileName), m_nLineNo(nLineNo), m_pszFuncName(NULL) {};
// 重载构造函数、文件名、行号和函数名
RTRACE(PCTSTR const pszFileName,int nLineNo,PCTSTR const pszFuncName):
m_pszFileName(pszFileName), m_nLineNo(nLineNo), m_pszFuncName(pszFuncName) {};
虚拟 ~RTRACE(void) {};
// 没有传递参数,例如 RTRACE()()
无效运算符()()常量
{
// 不传递参数,如果需要,只转储文件、行和函数
输出文件和线();
输出函数();
}
// 格式化字符串和传递的参数,例如 RTRACE()(_T("%s\n"), someStringVar)
void operator()(const PTCHAR pszFmt, ...) const
{
// 如果需要,转储文件、行和函数,后跟 TRACE 参数
输出文件和线();
输出函数();
// 执行标准的 TRACE 输出处理
va_list 指针;va_start(点,pszFmt);
INT len = _vsctprintf(pszFmt, ptr) + 1;
TCHAR* 缓冲区 = (PTCHAR) malloc( len * sizeof(TCHAR) );
_vstprintf(缓冲区,pszFmt,ptr);
输出调试字符串(缓冲区);
空闲(缓冲区);
}
私人的:
// 输出当前文件和行
内联 void OutputFileAndLine() 常量
{
如果 (m_pszFileName && _tcslen(m_pszFileName) > 0)
{
INT len = _sctprintf( _T("%s(%d): "), m_pszFileName, m_nLineNo ) + 1;
PTCHAR 缓冲区 = (PTCHAR) malloc( len * sizeof(TCHAR) );
_stprintf(缓冲区, _T("%s(%d): "), m_pszFileName, m_nLineNo );
输出调试字符串(缓冲区);
空闲(缓冲区);
}
}
// 输出当前函数名
内联 void OutputFunction() 常量
{
如果 (m_pszFuncName && _tcslen(m_pszFuncName) > 0)
{
INT len = _sctprintf( _T("%s: "), m_pszFuncName ) + 1;
PTCHAR 缓冲区 = (PTCHAR) malloc( len * sizeof(TCHAR) );
_stprintf(缓冲区, _T("%s:"), m_pszFuncName);
输出调试字符串(缓冲区);
空闲(缓冲区);
}
}
私人的:
PCTSTR 常量 m_pszFuncName;
PCTSTR 常量 m_pszFileName;
const int m_nLineNo;
};
#endif // _RTRACE
#endif // NDEBUG
TRACE 只是OutputDebugString的一个宏。因此,您可以轻松地制作自己的 TRACE 宏(或称其为其他名称)来调用OutputDebugString。
这是我见过的最简单的代码
#undef ATLTRACE
#undef ATLTRACE2
#define ATLTRACE2 CAtlTrace(__FILE__, __LINE__, __FUNCTION__)
#define ATLTRACE ATLTRACE2
在 MFC 中,TRACE 被定义为 ATLTRACE。在定义为的发布模式下:
#define ATLTRACE __noop
因此,使用 MFC 的开箱即用 TRACE,您实际上无法读取任何 TRACE 文本,因为它甚至不会被写出。您可以编写自己的 TRACE 函数,然后重新定义 TRACE 宏。你可以这样做:
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.
}