【问题标题】:Portable instrumentation便携式仪器
【发布时间】:2012-08-08 14:42:31
【问题描述】:

GCC 有一个很好的检测功能,可以让您在每次调用函数或每次函数返回时调用例程。

现在,我想创建自己的系统以使其可移植到其他编译器,并允许工具化我想要的功能(参数数量可能会有所不同),所以我在两种情况下都考虑了两个宏.我正在考虑制作某种配置文件,它只能通过定义子句激活。

#define FUNCT(t,function_name,...)   \
    (t) function_name(...) { \
        (void) *func_pointer = &(function_name); \
        start_data(func_pointer, myclock());

#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}

FUNCT(BOOL, LMP, const int prof, const int nmo))
    if (nmo <= 5 ||
        prof > (prof_l / 3)) {
        .... do long operations....
        RETURN(FALSE);
    }
    ... do more....
    RETURN(TRUE);
}

但我无法让它工作。有人可以帮我弄这个吗?或者这是一项难以完成的任务?

我想到的另一种选择是让函数在没有宏的情况下声明,如果无论如何都知道函数指针而不知道它的名称,就像在 VB 中当你和我一起调用表单时,它是一个通用别名。有可能吗?

【问题讨论】:

  • 我认为您需要从 RETURN 宏中删除 ;}

标签: c instrumentation


【解决方案1】:

使用gcc -E 调试您的宏。使用您发布的代码:

$ gcc -E t.c
# ... skip stuff ....

(BOOL) LMP(...) { (void) *func_pointer = &(LMP);
                  start_data(func_pointer, myclock());)
    if (nmo <= 5 ||
        prof > (prof_l / 3)) {
        .... do long operations....
        {stop_data(func_pointer, myclock()); return (FALSE);};
    }
    ... do more....
    {stop_data(func_pointer, myclock()); return (TRUE);};
}

(我添加了一些空格使其可读。)

您可以立即看到两个问题:函数参数没有像您想象的那样扩展,还有一个额外的 ) 来自某个地方。

要获取扩展的可变参数,请使用__VA_ARGS__,而不是...。流浪的) 在呼叫现场。

所以:

#define FUNCT(t,function_name,...)   \
    (t) function_name(__VA_ARGS__) { \
        (void) *func_pointer = &(function_name); \
        start_data(func_pointer, myclock());

#define RETURN(x) {stop_data(func_pointer, myclock()); return (x);}

FUNCT(BOOL, LMP, const int prof, const int nmo)
    if (nmo <= 5 ||
        prof > (prof_l / 3)) {
        .... do long operations....
        RETURN(FALSE);
    }
    ... do more....
    RETURN(TRUE);
}

至于这是否值得尝试(C99 附带可变参数宏,并非所有编译器都实现该标准,并且支持可能因编译器而异),我不确定。您可能最好使用每个编译器的本机分析工具 - 您将获得更好的结果,并希望减少开销。

【讨论】:

    【解决方案2】:

    在调用端而不是函数端检测函数要容易得多。宏可以与函数同名。在某处声明你的替换函数

    double myfunc_wrapper(int someArg) {
      double ret = 0;
      // do something before
       ...
      // now call it
      ret = (myfunc)(someArg);
    
      // Then do something after
      ....
      return ret;
    }
    

    只是为了确保将 () 放在调用本身周围,以确保始终调用函数而不是宏。

    然后用宏“重载”你的函数

    #define myfunc(...) mfunc_wrapper(__VA_ARGS__)
    

    有了这个想法,您可以在您感兴趣的编译单元中动态替换您的函数。

    【讨论】:

      【解决方案3】:

      除了Mat,使用#define RETURN(x) {...}还有人机工程学问题:

      if (test)
        RETURN (TRUE);
      else
        RETURN (FALSE);
      

      将评估为

      if (test)
        {...}
      ;           // <syntactical error
      else
        {...}
      ;
      

      【讨论】:

        猜你喜欢
        • 2010-12-07
        • 1970-01-01
        • 2012-06-03
        • 1970-01-01
        • 2011-02-01
        • 2011-02-20
        • 2016-06-20
        • 2011-03-06
        • 2013-11-24
        相关资源
        最近更新 更多