Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

global

I'm cleaning up some C code. There are global variables everywhere, but not all of them are used. I want to clean up those. But it's too much work to test them one by one. Is there are easy way to do that?

like image 873
TerryYin Avatar asked Oct 31 '11 01:10

TerryYin


4 Answers

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

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

This can be combined with the also-helpful gid(1) command (assuming you've run mkid(1) on your sources first):

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 helpful list of which files use which globals:

$ 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
...

It isn't perfect (as Ira points out), but it should be a good start.

like image 139
sarnold Avatar answered Nov 15 '22 20:11

sarnold


If they are only used within the file, you can declare them "static" and GCC will warn if they are never used.

If they are used from multiple files... I'm not sure how you could detect that, other than grepping or using an IDE, because they will show up as linker symbols and could in theory be accessed by any code that links with your code...

like image 44
Owen Avatar answered Nov 15 '22 22:11

Owen


This answer applies to the original question. The question has subsequently been changed.

It is impossible in principle to determine if a global variable is used or needed. Constructors can have side-effects, so even if a global is never accessed, it may still be needed.

True story: Programmer who shall remain nameless removed an 'unused' global from a production application. Unfortunately, the constructor for that global allocated memory from an allocator that initializes on first allocation.

As a result of him removing the unused global, the next object created using that allocator caused the allocator to initialize. Unfortunately, the initialization wasn't thread-safe (and was clearly documented as such) -- the purpose of the global was to ensure it initialized before any threads were created.

Let's just say there were very bad consequences (involving this company's largest customer -- a well-known three-letter government agency) and leave it at that.

A human being must make the determination that a global does not need to be created just because it is unused, and that can be a remarkably complicated decision to make.

like image 41
David Schwartz Avatar answered Nov 15 '22 20:11

David Schwartz


Easy? No. For a global variable X, you need to scan every compilation unit in your code for a potential access to X (a read, a write, or the generation of a reference). If there are no such accesses, then you can be reasonably sure (you don't have any assembly code, right?) that X isn't used.

It may even be the case that X is referenced in one of the above ways, but in fact has no actual effect on the program (e.g., X is read but ignore, written but not read, address taken but never dereferenced). That makes X effectively dead. Determining this requires global data flow analysis.

like image 45
Ira Baxter Avatar answered Nov 15 '22 21:11

Ira Baxter