C语言 有没有办法得到未使用函数的警告?

bwitn5fc  于 2023-02-11  发布在  其他
关注(0)|答案(6)|浏览(244)

我希望在代码库中找到未使用的函数-包括跨编译单元。我使用gcc作为我的编译器。
下面是一个例子:
foo.c(假设foo.h适当):

void foo() {
   ....
}

void bar() {
   ....
}

main.c

#include <stdio.h>
#include "foo.h"  

int main(void)  {
    bar();
    return 0;
}

在本例中,我希望得到foo()未被使用的警告。
-Wunused-function gcc选项:
-Wunused-function
当静态函数被声明但未被定义或非内联静态函数未被使用时发出警告。此警告由-Wall启用。
但它只适用于静态函数--在上面的例子中它不会产生警告。
我也会接受工具/脚本/其他编译器的建议,这些工具/脚本/其他编译器可以为我做这件事--尽管如果可能的话,我更愿意坚持使用gcc

ftf50wuq

ftf50wuq1#

Caolan Mc Namara,一个LibreOffice开发者,已经开发了一个小工具来检测LibreOffice源代码中的这类问题。他们有大约数千个函数和方法在LibreOffice中没有使用。他的工具是删除它们的关键因素。
它叫做callcatcher。它可以
收集定义的函数/方法并调用/引用减法
它直接作用于汇编器的输出,所以它只适用于x86和x86_64架构,它可以产生类似this的输出,你可以将它与传统的编译和链接gcc调用集成。
caulan同意它应该成为一个gcc插件。

egdjgwm8

egdjgwm82#

我知道你要求警告,并不喜欢使用gcc选项,但它真的很容易。
您可以使用链接器优化(--gc-sections)来删除应用程序中的死代码。

来自ld's手册页:

  • --gc-sections*--no-gc-sections启用未使用的输入部分的垃圾收集。在不支持此选项的目标上忽略此选项。可以通过在命令行上指定--no-gc-sections来恢复默认行为(不执行此垃圾收集)。
  • --print-gc-sections*--no-print-gc-sections列出所有被垃圾收集删除的部分。该列表打印在stderr上。仅当通过--gc-sections选项启用垃圾收集时,此选项才有效。可以通过在命令行上指定--no-print-gc-sections来恢复默认行为(不列出删除的部分)。

解释:

  • *--gc-sections**通过检查符号和重定位来决定使用哪些输入节。包含入口符号的节和所有包含命令行上未定义的符号的节将被保留,包含动态对象引用的符号的节也将被保留。请注意,在构建共享库时,链接器必须假定引用了任何可见符号。一旦确定了这组初始节,链接器递归地将任何被它们的重定位引用的节标记为已使用。2参见--entry和--undefined。

这个选项可以在进行部分链接时设置(使用选项-r启用)。在这种情况下,必须通过--entry或--undefined选项或链接器脚本中的"ENTRY"命令显式指定所保留符号的根。

wj8zmpe1

wj8zmpe13#

首先,如果你想让这样的警告在程序范围内出现,你当然需要-flto标志,因为它应该在链接时解决,而不是在编译每个单元的时候。但是我不认为GCC提供这样的警告,即使是这样。
那么,在一般情况下,我会理解提供它是不明智的(因为,例如,链接的libc可能有许多您的应用程序不需要的函数)。此外,应用程序可以使用dlsym技巧来访问一个明显未调用的函数...
然而,这是GCC插件或MELT扩展的一个很好的潜在用例示例,它将在某个地方注册每个调用事件,并在稍后的实用程序中查找所有未调用的函数。(但是为GCC编写插件或MELT扩展至少需要几天时间,因为您需要了解GCC的内部结构)。
您还可以使用分析技术来获取动态未使用(未调用)的函数。
欢迎通过电子邮件向我询问更多信息。

ego6inou

ego6inou4#

将gcc选项-ffunction-sections添加到编译中,将--gc-sections--print-gc-sections添加到link命令中,如果通过gcc调用链接器,则使用-Wl,--gc-sections,--print-gc-sections将它们传递给ld。
这将去除未使用的目标代码,您说过您不需要这些代码。在这种情况下,生成所需的输出后,请删除--gc-sections
您没有询问如何识别未使用的数据,但要做到这一点,还需要在编译中添加-fdata-sections选项。

u4vypkhs

u4vypkhs5#

我想gprof是最简单的解决方案,我编译了您提供的带有-pg选项的示例程序,以便在运行a.out时获得gmon.out(gprof可以稍后使用),然后我终于运行了gprof -z a.out gmon.out | tee output.txt。我可以在unused列表中找到你的函数foo!iidoe调用0次。-z是应该与gprof沿着使用的选项,用于跟踪未使用的例程。
感谢this线程提供的相应指针!
PS:gprof抛出了大量其他未使用的库函数沿着您未使用的函数foo。我真的不知道如何过滤这个:)

fwzugrvs

fwzugrvs6#

Eclipse CDT确实有代码分析功能,您可以设置它来标记未使用的静态函数和未使用的函数声明(以及其他有用的功能)。正如已经说过的,只有链接器才能分辨出某个(非静态)函数没有在某个二进制文件中使用...

相关问题