【问题标题】:Indented trace in C++C++ 中的缩进跟踪
【发布时间】:2011-06-02 14:18:32
【问题描述】:

我想为我们的大型 C++ 代码库开发缩进跟踪,这将特别有助于开发人员发现问题。我想要缩进的跟踪功能。例如,考虑以下代码:-

 void FunctionA()
{
     TR_ENTER("Function A");
     TR_PRINT("Dignostic message Function A");
     FunctionB(); // Call function B   
}

 void FunctionB()
{
    TR_ENTER("Function B");
    TR_PRINT("Dignostic message Function B");
    FunctionC(); // Call function B  
}

void FunctionC()
{
   TR_ENTER("Function C");
   TR_PRINT("Dignostic message Function C");          
}

如您所见,上面的调用是相互嵌套的。我想生成如下所示的跟踪日志:

Function A - Start
Dignostic message Function A
     Function B - Start
     Dignostic message Function B
            Function C - Start
            Dignostic message Function C
            Function C - End
     Function B - End
Function A - End

TR_ENTER 和 TR_PRINT 是我用作示例的一些宏。要说函数 start 我使用了 TR_ENTER 并打印了一些诊断消息我使用了 TR_PRINT。

如您所见,嵌套函数调用的跟踪是相互缩进的。我想知道是否有任何可用的东西,这样我就可以阻止自己重新发明轮子。

谢谢, 呸呸呸

【问题讨论】:

    标签: c++ windows trace


    【解决方案1】:

    您需要跟踪调用深度:

    class trace_entry;
    
    class trace_log {
    public:
        trace_log() : depth_(0) { }
    
    private:
        // noncopyable so we don't accidentally copy it
        trace_log(trace_log&);
        void operator=(trace_log);
    
        friend trace_entry;
    
        int depth_;
    };
    
    class trace_entry {
    public:
        trace_entry(trace_log& log, const std::string& frame)
            : log_(log), frame_(frame) {
            std::cout << std::string(4 * log.depth_, ' ') 
                      << "ENTER " << frame_ << std::endl;
            ++log_.depth_;
        }
    
        ~trace_entry() {
            --log_.depth_;
            std::cout << std::string(4 * log_.depth_, ' ') 
                      << "EXIT " << frame_ << std::endl;
        }
    private:
        // noncopyable so we don't accidentally copy it
        trace_entry(trace_entry&);
        void operator=(trace_entry);
    
        trace_log& log_;
        std::string frame_;
    };
    

    使用示例:

    void a(trace_log& log) {
        trace_entry e(log, "a");
    }
    
    void b(trace_log& log) { 
        trace_entry e(log, "b");
        return a(log);
    }
    
    int main() {
        trace_log log;
        trace_entry e(log, "main");
        b(log);
    }
    

    输出:

    ENTER main
        ENTER b
            ENTER a
            EXIT a
        EXIT b
    EXIT main
    

    这很容易扩展以支持替代形式的日志记录,允许额外的日志消息,以及您想做的任何其他事情。 (让trace_log 实际执行日志记录会好得多,但出于说明目的,这是演示您正在尝试做什么的最简单方法。)

    【讨论】:

    • 非常感谢詹姆斯...我会尝试这种方法。
    • 如果您知道自己是单线程的,您可以将 trace_log 设为全局变量。如果您是多线程的,您可能可以使用 perthread 变量来获得相同的效果。这样您就不需要修改应用程序中的每个函数调用来添加和传递trace_log 变量。
    • 另一件需要注意的事情.. 如果您编写 trace_entry(log,"foo"); 而不是正确的 trace_entry e(log,"foo");,编译器不会抱怨。第一个创建一个临时的并立即销毁它,立即输出 ENTER 和 EXIT 日志。第二种是正确的形式,在对象创建时输出 ENTER,在超出范围时输出 EXIT(通常在函数退出时)。
    • 即使它执行任务,问题是它如何适应您当前的架构。总有一天你会需要记录,然后你想控制输出流,格式等......最后再次编写任何现有的记录库;)
    【解决方案2】:

    那里有很多 C++ 日志库,特别是我可以推荐Log4cxx。他们将帮助您构建和配置应用程序的日志消息输出。要分析日志文件,您将需要一个额外的工具,例如 Apache Chainsaw

    另见Is there a log file analyzer for log4j files?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多