【问题标题】:Why doesn't `-finstrument-functions` work for me?为什么 `-finstrument-functions` 对我不起作用?
【发布时间】:2011-09-04 19:10:56
【问题描述】:

根据this answer,它应该打印所有函数名:

[root@ test]# cat hw.c
#include <stdio.h>

int func(void)
{  
  return 1;
}
int main(void)
{
  func();
  printf("%d",6);
  return 6;
}
[root@ test]# gcc -Wall hw.c -o hw -finstrument-functions
[root@ test]# ./hw 
6
[root@ test]# gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.

但为什么它对我不起作用?

【问题讨论】:

    标签: gcc


    【解决方案1】:

    这是来自 gcc 手册:

    -仪器功能

    生成仪器调用 进入和退出功能。只是 在函数输入之后和之前 函数退出,下面的profiling 函数将被调用 当前函数的地址和 它的呼叫站点。 (在某些平台上, __builtin_return_address 在当前函数之外不起作用,因此 呼叫站点信息可能不是 可用于分析功能 否则。)

    void __cyg_profile_func_enter (void *this_fn, void *call_site);

    void __cyg_profile_func_exit (void *this_fn, void *call_site);

    除非 somthing 实现了这些功能,否则您将收到链接器错误(这就是 MinGW 发生的情况)。可以想象,您的 GCC 版本提供的是空实现。

    我通过提供这个实现让它与 MinGW GCC 一起工作:

    #include  <stdio.h>
    
    void __cyg_profile_func_enter (void *this_fn, void *call_site) {
        printf( "entering %p\n", this_fn );
    }
    
    void __cyg_profile_func_exit (void *this_fn, void *call_site) {
        printf( "leaving %p\n", this_fn );
    }
    

    但这仅给出函数地址。我原以为应该有一个 GCC 默认实现,但似乎没有。

    人们也可能对this visualisation of the call tree 感兴趣,它使用 -fintrument-functions 标志 - 警告,我自己没有尝试过。

    【讨论】:

    • @Neil Butterworth,我可以手动将这两个函数添加到我的.c 文件中吗?
    • 可以,但实现起来相当复杂。
    • @Neil Butterworth ,我只想打印函数名,为什么这么复杂?
    • 您必须将我单独提供的代码编译为 C 代码,没有 -finstrument-functions 标志,然后将生成的 .o 文件与您的代码链接。这适用于 MingW GCC 4.5.1,但我不能保证其他平台。
    • ...或者不是单独编译,您可以将__attribute__((no_instrument_function)) 添加到__cyg_profile_func_XXX 函数的声明中,这将停止-finstrument-functions 检测检测。
    【解决方案2】:

    您实际上并没有实现任何检测。 -finstrument-functions 开关只是告诉 gcc 在入口处调用某个函数并退出到每个函数。但是你必须自己定义这些函数(通常这是通过链接一个分析器库来完成的)。

    【讨论】:

    • 使用-finstrument-functions 开关需要采取哪些额外步骤?我希望这将尽可能少......
    • @compile-fan:documentation 提到了必须实现的两个功能。不知道有没有现成的库使用它们。
    【解决方案3】:

    __cyg_profile_func_enter 和 __cyg_profile_func_exit 的编码并不复杂。最简单的解决方案是确保上述函数将地址详细信息写入文件,并有一个单独的过程从文件中读取地址并使用可执行文件的符号表解析它们。如果您尝试在函数本身中进行地址解析,可能需要一些时间。

    我遇到了以下文章 - http://balau82.wordpress.com/2010/10/06/trace-and-profile-function-calls-with-gcc/

    为此目的使用 binutils 中的 addr2line。检查这是否对您有帮助

    【讨论】:

    • 有时.. 仅打印 fn 名称以调试正确性非常有用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 2016-02-27
    • 2019-01-13
    • 2015-09-07
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多