Is there a way to identify the entire unused global variable in project C?

I am clearing the C code. There are global variables all over the world, but not all of them are used. I want to clean them. But he works too much to test them one by one. Is there an easy way to do this?

+7
source share
6 answers

You can create a list of all global variables in your directory using the very useful ctags(1) command with the -x command-line option:

 ctags -x --c-kinds=v --file-scope=no *.c 

This can be combined with the useful gid(1) command (if you first run mkid(1) in your sources):

 for name in `ctags -x --c-kinds=v --file-scope=no *.c | awk '{print $1;}' | sort -u` ; do gid -R filenames $name ; done 

This gives you a useful list of files that use global variables:

 $ for name in `ctags -x --c-kinds=v --file-scope=no *.c | awk '{print $1;}' | sort -u` ; do gid -R filenames $name ; done basedir parser.h ./{parser_include,parser_main}.c binary_input parser_main.c cache_fd parser.h ./{parser_interface,parser_main}.c conf_quiet parser.h parser_main.c conf_verbose parser.h ./{parser_interface,parser_main}.c ... 

This is not ideal (as Ira points out ), but it should be a good start.

+5
source

If they are used only in the file, you can declare them β€œstatic” and GCC will warn you if they are never used.

If they are used from several files ... I’m not sure how you could find this apart from grepping or using the IDE, because they will appear as linker symbols and can be theoretically accessible by any code that links to your code ...

+3
source

This answer relates to the original question. Subsequently, the question was changed.

In principle, it is impossible to determine whether a global variable is used or needed. Constructors can have side effects, so even if global access is never available, it might still be needed.

The true story: a programmer who remains nameless has removed the β€œunused" global from the production application. Unfortunately, the constructor for this global allocated memory from the allocator, which is initialized at the first allocation.

As a result of deleting an unused global object, the next object created using this allocator caused the allocator to initialize. Unfortunately, the initialization was not thread safe (and was clearly documented as such) - the goal of the global was to ensure that it was initialized before any threads were created.

Let's say there were very bad consequences (with the participation of this largest client of this company - the well-known three-letter government agency) and leave it to that.

A person must decide that the global does not need to be created just because it is not used, and this can be an extremely difficult decision.

+3
source

Easy? Not. For the global variable X, you need to scan each compilation unit in your code for potential access to X (read, write or link generation). If there are no such accesses, then you can be pretty sure (you don't have assembly code, right?) That X is not used.

Perhaps even if X refers to one of these methods, but does not actually have an actual effect on the program (for example, X is read, but ignored, written, but not read, the address is accepted, but not dereferenced), This makes X actually dead. A global data flow analysis is required to determine this.

+2
source

(@ChrisLutz posted this idea as a comment, but I thought about it before I read the comment, so I will post it anyway. I will try to add some value by expanding it.)

In a separate copy of the source code, comment out the declarations of all your global variables and recompile everything. Compare the list of variables that you commented with those indicated in the compiler error messages. Everything that is not indicated in the error message is not used.

Please note that your build process may not try to build all of some compilations, which may give you some incomplete results.

A slightly different approach that avoids this problem is iterative: comment out all your global variables, try to build, and then uncomment the declarations for anything the compiler complained about. Iterate until you get a clean build, and see what else is commented out.

+1
source

Doxygen can give you a list of options for using global variables.

0
source

All Articles