Mfc 如何在释放模式下启用跟踪宏?

Mfc 如何在释放模式下启用跟踪宏?,mfc,macros,trace,Mfc,Macros,Trace,在调试模式下编译代码时,可用于向调试器输出诊断消息。在释放模式下,我需要相同的消息。有没有办法做到这一点 (请不要浪费时间讨论为什么我不应该在发布模式下使用跟踪:-)在MFC中,跟踪定义为ATLTRACE。在释放模式下,定义为: #define ATLTRACE __noop 因此,使用MFC中的开箱即用跟踪,您实际上无法读取任何跟踪文本,因为它甚至不会被写出。您可以编写自己的跟踪函数,然后重新定义跟踪宏。你可以这样做: void MyTrace(const CStrin

在调试模式下编译代码时,可用于向调试器输出诊断消息。在释放模式下,我需要相同的消息。有没有办法做到这一点


(请不要浪费时间讨论为什么我不应该在发布模式下使用跟踪:-)

在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.
}
void trace(const char* format, ...)
{
   char buffer[1000];

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

   OutputDebugString(buffer);
}

TRACE只是一个宏。因此,您可以轻松地创建自己的跟踪宏(或将其称为其他名称)来调用。

实际上,跟踪宏比OutputDebugString灵活得多。它采用printf()样式的格式字符串和参数列表,而OutputDebugString只采用单个字符串。为了在发布模式下实现完整的跟踪功能,您需要执行以下操作:

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.
}
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添加到发布模式预处理器定义中

也许有人会发现它的用处:-)

约翰

#布拉格语一次 //------------------------------------------------------------------------------------------------ // //作者:约翰·卡伦 //日期:2006/04/12 //基于:变量参数列表的MSDN示例和跟踪的ATL实现。 // //描述:通过重写 //跟踪宏定义,并根据RTRACE类和重载进行重新定义 //运算符()。跟踪输出是通过直接调用OutputDebugString()生成的。 // // //用法:添加到stdafx.h的末尾,并将_RTRACE添加到预处理器定义(通常为 //对于发布版本,尽管调试版本将忽略该标志。 // //------------------------------------------------------------------------------------------------ #ifdef_调试 //NL定义为写入FTRACE(_T(“\n”))的快捷方式;例如,改为写入FTRACE(NL); #定义NL\u T(“\n”) #定义LTRACE跟踪(\u T(“%s(%d):”)、文件、行跟踪 #定义FTRACE跟踪(\u T(“%s(%d):%s:”)、文件、行、函数跟踪 #else/\u调试 #ifdef_RTRACE #未定义跟踪 #定义跟踪RTRACE() #定义LTRACE RTRACE(_文件,_行) #定义FTRACE RTRACE(_文件_,_线_,_函数_u) #定义NL\u T(“\n”) 等级赛 { 公众: //默认构造函数,无参数 RTRACE(void):m_pszFileName(NULL)、m_nLineNo(0)、m_pszFuncName(NULL){}; //重载构造函数、文件名和行号 RTRACE(PCTSTR常量pszFileName,int NLINNO): m_pszFileName(pszFileName)、m_nLineNo(nLineNo)、m_pszFuncName(NULL){}; //重载构造函数、文件名、行号和函数名 RTRACE(PCTSTR常量pszFileName、int NLINNO、PCTSTR常量pszFuncName): m_pszFileName(pszFileName)、m_nLineNo(nLineNo)、m_pszFuncName(pszFuncName){}; 虚~RTRACE(void){}; //未传递任何参数,例如RTRACE()() void运算符()()常量 { //没有传递任何参数,只要在请求时转储文件、行和函数即可 OutputFileAndLine(); OutputFunction(); } //格式化字符串和传递的参数,例如RTRACE() void运算符()(常量PTCHAR pszFmt,…)常量 { //如果请求,转储文件、行和函数,后跟跟踪参数 OutputFileAndLine(); OutputFunction(); //执行标准跟踪输出处理 VAU列表ptr;VAU启动(ptr、pszFmt); INT len=_vsctprintf(pszFmt,ptr)+1; TCHAR*buffer=(PTCHAR)malloc(len*sizeof(TCHAR)); _vstprintf(缓冲区、pszFmt、ptr); OutputDebugString(缓冲区); 自由(缓冲); } 私人: //输出当前文件和行 内联void OutputFileAndLine()常量 { 如果(m_pszFileName&&u tcslen(m_pszFileName)>0) { INT len=_sctprint(_T(“%s(%d):”),m_pszFileName,m_nLineNo)+1; PTCHAR缓冲区=(PTCHAR)malloc(len*sizeof(TCHAR)); _stprintf(缓冲区,_T(“%s(%d):”),m_pszFileName,m_nLineNo); OutputDebugString(缓冲区); 自由(缓冲); } } //输出当前函数名 内联void OutputFunction()常量 { 如果(m_pszFuncName&&u tcslen(m_pszFuncName)>0) { INT len=_sctprintf(_T(“%s:”),m_pszFuncName)+1; PTCHAR缓冲区=(PTCHAR)malloc(len*sizeof(TCHAR)); _stprintf(缓冲区,_T(“%s:”),m_pszFuncName); OutputDebugString(缓冲区); 自由(缓冲); } } 私人: PCTSTR const m_pszFuncName; PCTSTR const m_pszFileName; 米尼诺常数; }; #endif/\u RTRACE #endif//NDEBUG
这是我见过的最简单的代码

#undef ATLTRACE
#undef ATLTRACE2

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

我知道这只是一个示例,但在这个示例中存在巨大的缓冲区溢出可能性(按原样)。对于ATL项目,我有一个drop-in类,它重新定义
ATLTRACE
宏并映射到
OutputDebugString
(包括接受灵活数量的参数):