可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'd like to find unused functions in a codebase - including across compilations units. I'm using gcc as my compiler.
Here's an example:
foo.c
(assume appropriate foo.h
):
void foo() {
....
}
void bar() {
....
}
main.c
:
#include <stdio.h>
#include "foo.h"
int main(void) {
bar();
return 0;
}
In this example, I'd like to get warned about foo()
not being used.
There is the -Wunused-function
gcc option:
-Wunused-function
Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is
enabled by -Wall.
but it's only for static functions - it won't produce a warning on the example above.
I'll also accept suggestions of tools/scripts/other compilers that can do this for me - though I'd prefer to stick with gcc
if possible.
回答1:
Caolan Mc Namara, a LibreOffice developer, has made a small tool to detect this type of thing in LibreOffice source code. They had around thousands functions & methods unused in LibreOffice. His tool is a key element for removing them.
It's called callcatcher. It can
collect functions/methods defined and subtract called/referenced
It works directly on assembler output and so, it works only for x86 and x86_64 architecture. It can produce output like this. You can integrate it with your traditional compiling and linking call to gcc.
Caolan agrees that it should become a gcc plugin.
回答2:
I know you asked for warnings and prefers not to use gcc option but it is really easy.
You can use linker optimization (--gc-sections) in order to remove the dead code from your application.
From gcc's man page:
--gc-sections
--no-gc-sections
Enable garbage collection of unused input sections. It is ignored on targets that do not support this option. The default behaviour (of not performing this garbage collection) can be restored by specifying --no-gc-sections on the command line.
--gc-sections decides which input sections are used by examining symbols and relocations. The section containing the entry symbol and all sections containing symbols undefined on the command-line will be kept, as will sections containing symbols referenced by dynamic objects. Note that when building shared libraries, the linker must assume that any visible symbol is referenced. Once this initial set of sections has been determined, the linker recursively marks as used any section referenced by their relocations. See --entry and --undefined.
This option can be set when doing a partial link (enabled with option -r). In this case the root of symbols kept must be explicitly specified either by an --entry or --undefined option or by a "ENTRY" command in the linker script.
回答3:
First, if you want such warnings to be program-wide, you certainly need the -flto
flag, since it should be resolved at link time, not at time of compilation of each individual unit. But I don't think that GCC provide such warnings, even this way.
Then, in the general case, I would understand it won't be wise to provide it (because e.g. the linked libc
probably has a lot of functions your application don't need). Also, an application could use dlsym
tricks to reach an apparently uncalled function...
However, it is a good example of a potential use case for a GCC plugin or MELT extension, which would register each call occurrence somewhere, with a later utility finding all non-called functions. (But coding a plugin or a MELT extension for GCC will take you several days at least, because you'll need to understand GCC internals).
You could also use profiling techniques to get the dynamically unused (not called) functions.
Feel free to ask me more by email.
回答4:
Eclipse CDT does have code analysis, which you can set to mark unused static functions and unused function declarations (among other useful things).
As already told, only linker could tell certain (non-static) function was not used in certain binary...
回答5:
gprof
is the simplest solution I guess. I compiled the sample program you've put up with -pg
option so that we get the gmon.out
when we run a.out
(which gprof can use later) and then I finally ran gprof -z a.out gmon.out | tee output.txt
. I could find your function foo
in the unused list! i.e called 0
times. -z
is the option you should use along with gprof
to track unused routines.
Thanks to this thread for the appropriate pointer!
PS: gprof
threw up a slew of other unused library functions along with your unused function foo
. I seriously don't know how to filter this :)