【问题标题】:How to enable the TRACE macro in Release mode?如何在 Release 模式下启用 TRACE 宏?
【发布时间】:2010-09-06 20:34:40
【问题描述】:

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

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

【问题讨论】:

  • 对于 ATL 项目,我有一个插入类,它重新定义 ATLTRACE 宏并映射到 OutputDebugString(包括接受灵活数量的参数):alax.info/blog/tag/outputdebugstring

标签: mfc macros trace


【解决方案1】:

这是我见过的最简单的代码

#undef ATLTRACE
#undef ATLTRACE2

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

http://alax.info/blog/1351

【讨论】:

    【解决方案2】:

    在 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.
    }
    

    【讨论】:

      【解决方案3】:

      几年前,我需要类似的功能,所以我拼凑了以下代码。只需将其保存到文件中,例如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

      【讨论】:

        【解决方案4】:

        实际上,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);
        }
        

        【讨论】:

        • 我知道这只是一个例子,但在这个例子中存在巨大的缓冲区溢出可能性。
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-06-20
          • 2023-03-18
          • 1970-01-01
          • 1970-01-01
          • 2022-12-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多