首页 / 知识

关于mfc:如何在发布模式下启用TRACE宏?

2023-04-13 05:04:00

关于mfc:如何在发布模式下启用TRACE宏?

How to enable the TRACE macro in Release mode?

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

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


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

1
2
3
4
5
6
7
8
9
10
11
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添加到Preprocessor定义的发布模式。

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

约翰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#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("\
")); for example, instead write FTRACE(NL);
#define NL _T("\
")
#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("\
")

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\
"), 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

TRACE只是OutputDebugString的宏。因此,您可以轻松地制作自己的TRACE宏(或以其他方式调用)以调用OutputDebugString。


我看到的最简单的代码

1
2
3
4
5
#undef ATLTRACE
#undef ATLTRACE2

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

看到
http://alax.info/blog/1351


在MFC中,TRACE被定义为ATLTRACE。并在发布模式下定义为:

1
#define ATLTRACE            __noop

因此,使用MFC提供的现成的TRACE,您实际上将无法读取任何TRACE文本,因为它甚至都不会被写入。您可以改为编写自己的TRACE函数,然后重新定义TRACE宏。您可以执行以下操作:

1
2
3
4
5
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.
}


启用消息编译诊断

最新内容

相关内容

热门文章

推荐文章

标签云

猜你喜欢