有没有办法得到关于未使用功能的警告?

时间:2012-02-01 05:50:02

标签: c gcc gcc-warning

我想在代码库中找到未使用的函数 - 包括跨编译单元。我正在使用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

6 个答案:

答案 0 :(得分:43)

LibreOffice开发人员

Caolan Mc Namara已经制作了一个小工具来检测LibreOffice源代码中的这种类型的东西。他们有大约数千个功能和LibreOffice中未使用的方法。他的工具是移除它们的关键因素。

它被称为callcatcher。它可以

  

收集定义的函数/方法并减去called / referenced

它直接在汇编程序输出上工作,因此,它仅适用于x86和x86_64体系结构。它可以产生类似this的输出。您可以将它与传统的编译和链接调用集成到gcc。

Caolan同意它应该成为一个gcc插件。

答案 1 :(得分:3)

首先,如果您希望此类警告在程序范围内,您当然需要-flto标志,因为它应该在链接时解决,而不是在编译每个单元时。但我不认为海湾合作委员会会提供这样的警告,即便如此。

然后,在一般情况下,我会理解提供它是不明智的(因为例如链接的libc可能有很多你的应用程序不需要的函数)。此外,应用程序可以使用dlsym技巧来达到一个明显不受欢迎的功能......

然而,它是GCC插件或MELT扩展的潜在用例的一个很好的例子,它将在某处注册每个调用事件,后来的实用程序找到所有非调用函数。 (但是为GCC编写插件或MELT扩展名至少需要几天时间,因为你需要了解GCC的内部结构。)

您还可以使用分析技术来获取动态未使用(未调用)的函数。

随时通过电子邮件向我提问。

答案 2 :(得分:3)

我知道你要求警告并且不想使用gcc选项,但这很容易。

您可以使用链接器优化(--gc-sections)从应用程序中删除死代码。

来自gcc的手册页:

<强> - GC-部分 --no-GC-节 启用未使用输入节的垃圾收集。在不支持此选项的目标上会被忽略。可以通过在命令行上指定--no-gc-sections来恢复默认行为(不执行此垃圾回收)。

- gc-sections 通过检查符号和重定位来决定使用哪些输入节。将保留包含条目符号的部分和包含在命令行上未定义的符号的所有部分,以及包含动态对象引用的符号的部分。请注意,在构建共享库时,链接器必须假定引用了任何可见的符号。确定此初始部分集后,链接器将递归地标记为使用其重定位引用的任何部分。请参阅--entry和--undefined。

执行部分链接时可以设置此选项(使用选项-r启用)。在这种情况下,必须通过--entry或--undefined选项或链接描述文件中的“ENTRY”命令显式指定保留的符号根。

答案 3 :(得分:2)

将gcc选项-ffunction-sections添加到编译中,并将--gc-sections--print-gc-sections添加到链接命令中。如果您通过gcc调用链接器,请使用-Wl,--gc-sections,--print-gc-sections将其链接到ld。

这将删除您说不想使用的未使用的对象代码。在这种情况下,一旦生成所需的输出,请删除--gc-sections

您并不是要确定未使用的数据,而是要在编译中添加-fdata-sections选项。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

gprof是我猜的最简单的解决方案。我编译了您使用-pg选项设置的示例程序,以便在运行gmon.out时获取a.out(gprof可以在以后使用)然后我最终运行{{1} }。我可以在未使用的列表中找到您的函数gprof -z a.out gmon.out | tee output.txt!即称foo次。 0是您应该与-z一起使用的选项,用于跟踪未使用的例程。

感谢this线程提供适当的指针!

PS:gprof抛出了大量其他未使用的库函数以及未使用的函数gprof。我真的不知道如何过滤这个:)