• C++中的函数调用跟踪Trace功能简单实现


    我们所使用的每个软件产品都包含这样或那样的跟踪功能。
    跟踪,英文Trace,又叫做追踪。
    软件中的跟踪就是仅仅地跟在执行者的后面进行监视。
    当代码超过几千行时,跟踪就显得很重要了。
    调试、维护和理解大中型软件的执行流程是很重要的,这是跟踪的基本功能。
    在C++中,有许多方法可以进行函数调用跟踪。
    其中最简单的方法是在刚进入函数时打印
    "Entering function X",在返回函数之前进行打印"Leaving function X"
    但是,这需要进行很多工作,尤其是在函数具有多个
    return语句的情况下。

    解决上述问题的一种方法是使用跟踪对象。
    您创建一个类,该类的构造函数将打印输入消息,存储函数名称,并且其析构函数将打印离开消息。
    然后,将该类的实例创建为局部变量。当实例化对象时(调用函数时会发生这种情况),将打印enter消息。
    当函数离开时,无论何时,何地或如何发生,对象都会被破坏,并会显示离开消息。
    注意,trace对象不应该添加到小的、频繁执行的函数中去。

    现在,这样是如何实现的呢?可能是这样简单的事情:

     1 struct tracer
     2 {
     3     std::string name_;  // Name of the function
     4 
     5     tracer(std::string const& name)
     6         : name_(name)
     7     {
     8         std::clog << "Entering function " << name_ << std::endl;  // Flushing is important
     9     }
    10 
    11     ~tracer()
    12     {
    13         std::clog << "Leaving function " << name_ << std::endl;  // Flushing is still important
    14     }
    15 };

    这就是所需要的基础。现在使用它非常简单:

    1 void some_class::some_member_function()
    2 {
    3     tracer _unique_name_{"some_class::some_member_function");
    4 
    5     // Lots of code and multiple `return` statements...
    6 
    7 }

    这是基本用法。它具有一些缺点,因为将始终启用跟踪。例如,发布版本很少需要它,因此只有在_DEBUG定义宏时才使用它才是一个好的开始。拥有一个特殊的TRACING_ENABLED可能会更好,因此即使在某些有用的发行版中也可以启用它。还可以添加额外的逻辑来检查在运行时设置的标志。

    下面一个完整的示例解决方案,在编译时使用预处理器宏来启用和禁用跟踪。

     1 #pragma once
     2 #ifndef TRACING_H
     3 #define TRACING_H
     4 
     5 #include <string>
     6 #include <iostream>
     7 #include <iomanip>
     8 
     9 // Simple structure to handle function-call tracing.
    10 
    11 // On debug builds, always build with tracing enabled unless explicitly disabled
    12 #if defined(_DEBUG) && !defined(TRACING_DISABLED)
    13 # define TRACING_ENABLED
    14 #endif
    15 
    16 // Define a preprocessor macro to help with the tracing
    17 #ifdef TRACING_ENABLED
    18 # define TRACE() tracing::tracer _tracer_object__ ## __COUNTER__ {__func__, __FILE__, __LINE__}
    19 #else
    20 # define TRACE() // Nothing
    21 #endif
    22 
    23 #ifdef TRACING_ENABLED
    24 namespace tracing
    25 {
    26     class tracer
    27     {
    28     public:
    29         tracer() = delete;  // Disallow default construction
    30         tracer(tracer const&) = delete;  // Disallow copy construction
    31         tracer(tracer&&) = delete;  // Disallow move construction
    32         tracer& operator=(tracer const&) = delete;  // Disallow copy assignment
    33         tracer& operator=(tracer&&) = delete;  // Disallow move assignment
    34 
    35         tracer(std::string const& fun, std::string const& file, int const line)
    36             : function_name{fun}, file_name{file}, line_number{line}
    37         {
    38             std::clog << "TRACE: Entering function " << function_name << " (" << file_name << ':' << line_number << ')' << std::endl;
    39         }
    40 
    41         ~tracer()
    42         {
    43             std::clog << "TRACE: Leaving function " << function_name << std::endl;
    44         }
    45 
    46     private:
    47         std::string function_name;
    48         std::string file_name;
    49         int         line_number;
    50     };
    51 }
    52 #endif // TRACING_ENABLED
    53 
    54 #endif // TRACING_H

    使用上述头文件的示例程序:

    #include "tracing.h"
    
    struct foo
    {
        int bar(int value)
        {
            TRACE();
    
            if (value < 10)
                return value * 2;
            else
                return value * 3;
        }
    };
    
    int main()
    {
        TRACE();
    
        foo my_foo;
        my_foo.bar(20);
        my_foo.bar(5);
    }

    如上所示,程序的输出可能类似于

    输出可能会因所使用的编译器而异。

  • 相关阅读:
    windows cluster 心跳检测阀值优化
    添加普通用户为sudoer
    每日备份脚本目录shell
    linux基础配置
    表变量 临时表 使用场景
    mysql分组排序row_number() over(partition by)
    replication_较少延迟时间
    SQL Server 参数化 PARAMETERIZATION
    thinkPHP RBAC模块
    thinkPHP 微信sdk
  • 原文地址:https://www.cnblogs.com/MakeView660/p/12531566.html
Copyright © 2020-2023  润新知