【问题标题】:How to tell gcc to instrument the code with calls to my own function each _line_ of code?如何告诉 gcc 通过对我自己的函数的每一行代码的调用来检测代码?
【发布时间】:2011-04-28 07:50:35
【问题描述】:

比如有源:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number);

void func1() {
    func3();
    func4();
}

void foo() {
    func1();
    if(qqq) {
        func2();
    };
    func3();
    func4();
    for(...) {
        func5();
    }
}

它应该编译为:

void my_special_debugging_function(const char* function_name, const char* file_name, int line_number);

void func1() {
    my_special_debugging_function("func1", "prog.c", 3);
    func3();
    my_special_debugging_function("func1", "prog.c", 4);
    func4();
    my_special_debugging_function("func1", "prog.c", 5);
}

void foo() {
    my_special_debugging_function("foo", "prog.c", 8);
    func1();
    my_special_debugging_function("foo", "prog.c", 9);
    if(qqq) {
        my_special_debugging_function("foo", "prog.c", 10);
        func2();
        my_special_debugging_function("foo", "prog.c", 11);
    };
    my_special_debugging_function("foo", "prog.c", 12);
    func3();
    my_special_debugging_function("foo", "prog.c", 13);
    func4();
    my_special_debugging_function("foo", "prog.c", 14);
    for(...) {
        my_special_debugging_function("foo", "prog.c", 15);
        func5();
        my_special_debugging_function("foo", "prog.c", 16);
    }
    my_special_debugging_function("foo", "prog.c", 17);
}

当然,my_special_debugging_function 应该可以使用backtrace 函数。

有 gcc 的选项吗?或者是否有工具可以在源代码级别执行此操作? (例如,用我的函数生成其他 C 源代码)

@相关 How to "interleave" C/C++ souce with my string (only inside functions at appropriate places)?

@相关 What profiler should I use to measure _real_ time (including waiting for syscalls) spend in this function, not _CPU_ one

【问题讨论】:

  • 不完全是这样。不过,您应该注意 __FILE__、__LINE__ 和 __func__ 宏。
  • @simonhf 它是否在函数内进行检测?它可以将它的东西添加到函数内部的每个源代码行吗?
  • 它通过-finstrument-functions自动检测每个函数的入口和出口点。但是,此外,您可以在函数中手动添加永久检测宏。自动和手动添加的宏都尊重为函数设置的相同的单个详细程度。它与您上面描述的非常相似,除了 func1() 中的所有宏都尊重为 func1() 设置的详细程度,而 foo() 中的所有宏都尊重为 foo() 设置的详细程度。

标签: c gcc profiling instrumentation


【解决方案1】:

请参阅 GCC 文档中的 -finstrument-functions。您可能想在调试功能中使用dladdr(),这可能还需要与-Wl,-export-dynamic链接。

【讨论】:

  • -finstrument-functions 在功能级别工作。如何让它按行工作?
  • @Vi:我认为没有任何方法可以告诉 GCC 这样做,而无需预处理器技巧和对源代码的编辑。
  • @nategoose,好的,重新询问源代码的技巧:stackoverflow.com/questions/3989992/…
【解决方案2】:

如果您使用的是 gcc 版本 >=4.5,您可以write a gcc plugin 以您喜欢的方式处理 AST。但该解决方案将取决于编译器。

您还可以obtain AST from eclipse CDT 并从该输入重新生成 C 代码。

【讨论】:

    【解决方案3】:

    如另一个答案所述,I don't think that there is any way to tell GCC to do that, without preprocessor tricks and edits to the source code. – nategoose

    【讨论】:

      【解决方案4】:

      您可以使用 aspectc++ 轻松完成。从 aspectc.org 获取此编译器 这是一个满足您要求的简单方面。 Trace.ah

      #ifndef __trace_ah__
      #define __trace_ah__
      #include <cstdio>
      #include <iostream>
      using namespace std;
      template <int I> struct ArgPrinter
      {
      template <class JP> static inline void work (JP &tjp) {
      ArgPrinter<I - 1>::work (tjp);
      cout << *tjp.template arg<I - 1> () << " ";
      }
      };
      template <> struct ArgPrinter<0>
      {
       template <class JP> static inline void work (JP &tjp) {}
      };
      
      
      aspect trace {
      int depth=-1;
      pointcut virtual methods() = "% ...::%(...)";
      
      template <class JP> void print_args (JP &tjp)
          {
               ArgPrinter<JP::ARGS>::work (tjp);
          }
      
      advice execution (methods()) : before ()
      {
          depth++;
          cout << "Enter -> " << JoinPoint::signature() <<" Depth:"<<depth<< " ARGS " << JoinPoint::ARGS <<" (";
          tjp->arg(0);
          print_args (*tjp);
          cout<<")"<<endl;
          cout<< "console--"<<endl;
      }
      
      advice execution("% ...::%(...)" && !"void ...::%(...)") : after()
      {
          cout<< "--console"<<endl;
          JoinPoint::Result res = *tjp->result();
          cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET " << res<<endl;
          depth--;
      }
      advice execution("void ...::%(...)") : after()
      {
          cout<< "--console"<<endl;
          cout << "Exit <- " << tjp->signature()<< " Depth: "<<depth<< " RET void"<<endl;
          depth--;
      }
      };
      #endif
      

      使用 ac++ 编译器将此方面与您的项目一起编译,然后运行您的程序。然后您应该在控制台中看到跟踪。 追踪快乐!

      【讨论】:

      • OP 不要求 c++ 解决方案
      猜你喜欢
      • 2014-12-16
      • 1970-01-01
      • 2011-01-19
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2021-11-06
      • 2016-02-29
      • 1970-01-01
      相关资源
      最近更新 更多