When I'm writing C - code I solely use an editor and gcc. I was wondering if anyone could suggest a good and simple tool that will find unused variables, function declarations and possibly make some optimisations.
Does anybody know a good tool?
When I'm writing C - code I solely use an editor and gcc. I was wondering if anyone could suggest a good and simple tool that will find unused variables, function declarations and possibly make some optimisations.
Does anybody know a good tool?
If you run gcc with -Wall, it'll catch some of the things you mention, such as unused variables (and perhaps unused functions). In terms of optimizations, I don't, though in general the compiler is smart enough to make the kinds of optimizations that matter, so I wouldn't worry too much. Just don't use horrible algorithms. ;-)
Lint is the classic tool for checking style on C programs. There's more modern incarnation of it called Splint. This Wikipedia entry has a list of static code analysis tools, some free, some commercial.
As Dan Fego pointed out, GCC can catch unused variables and unused static functions. It won't normally find unused extern functions as it normally works one source file at a time.
GCC (v4.3.2) has hundreds if not thousands of options. One that might help is '--combine
' to combine source files (as long as you're not in the habit of putting the same function or variable names inside different source files).
The option '--help
' tells you more; the options '--help=optimizers
' and '--help=warnings
' each give you a couple hundred lines of output. The warnings include:
-Wunused This switch lacks documentation
-Wunused-function Warn when a function is unused
-Wunused-label This switch lacks documentation
-Wunused-macros Warn about macros defined in the main file that
are not used
-Wunused-parameter Warn when a function parameter is unused
-Wunused-value Warn when an expression value is unused
-Wunused-variable Warn when a variable is unused
Added: this is a script called glint
that I use to sanitize my code. It is quite old so it doesn't use the '#!/bin/sh
' notation for the first line and it says '$*
' instead of '"$@"
', both of which should be fixed, but neither needs to be fixed urgently. Note that even though GCC 4.x no longer supports the '-fwriteable-strings
' option, it still supports the '-Wwrite-strings
' option and that has value.
This script demonstrates that you can get a lot of mileage out of existing tools with just a small amount of work. You can configure just about every option it uses - albeit mainly via the environment rather than the command line. Of course, you can add extra warning options to the command line; what you can't do is remove predetermined options except via the environment. But that's OK; they're chosen by default for good reasons. These days, I'd probably set 'GLINT_ANSI=-std=c99
' or fix the script; I've not been using it much of late since I code fairly closely to the standard that glint
enforces. (Note that the '-o /dev/null
' means that you can only do one file at a time; hack to fix!)
: "@(#)$Id: glint.sh,v 1.5 2002/08/09 21:40:52 jleffler Exp jleffler $"
#
# Use GCC as excruciatingly pedantic lint
# Not a complete replacement for lint -- it doesn't do inter-file checking.
# Now configurable via the environment.
# Use GLINT_EXTRA_FLAGS to set extra flags via the environment.
# NB: much Solaris code won't work with -undef enabled.
: ${GLINT_GCC:='gcc'}
: ${GLINT_ANSI='-ansi'}
: ${GLINT_FNO_COMMON='-fno-common'}
: ${GLINT_FSHORT_ENUMS='-fshort-enums'}
: ${GLINT_PEDANTIC='-pedantic'}
: ${GLINT_UNDEF='-undef'}
: ${GLINT_W='-W'}
: ${GLINT_WAGGREGATE_RETURN='-Waggregate-return'}
: ${GLINT_WALL='-Wall'}
: ${GLINT_WCAST_ALIGN='-Wcast-align'}
: ${GLINT_WCAST_QUAL='-Wcast-qual'}
: ${GLINT_WCONVERSION='-Wconversion'}
: ${GLINT_WMISSING_DECLARATIONS='-Wmissing-declarations'}
: ${GLINT_WREDUNDANT_DECLS='-Wredundant-decls'}
: ${GLINT_WMISSING_PROTOTYPES='-Wmissing-prototypes'}
: ${GLINT_WNESTED_EXTERNS='-Wnested-externs'}
: ${GLINT_WPOINTER_ARITH='-Wpointer-arith'}
: ${GLINT_WSHADOW='-Wshadow'}
: ${GLINT_WSTRICT_PROTOTYPES='-Wstrict-prototypes'}
: # ${GLINT_WTRADITIONAL='-Wtraditional'}
: ${GLINT_WWRITE_STRINGS='-Wwrite-strings'}
exec ${GLINT_GCC} \
${GLINT_ANSI} \
${GLINT_FNO_COMMON} \
${GLINT_FSHORT_ENUMS} \
${GLINT_PEDANTIC} \
${GLINT_UNDEF} \
${GLINT_WAGGREGATE_RETURN} \
${GLINT_WALL} \
${GLINT_WCAST_ALIGN} \
${GLINT_WCAST_QUAL} \
${GLINT_WCONVERSION} \
${GLINT_WMISSING_DECLARATIONS} \
${GLINT_WREDUNDANT_DECLS} \
${GLINT_WMISSING_PROTOTYPES} \
${GLINT_WNESTED_EXTERNS} \
${GLINT_WPOINTER_ARITH} \
${GLINT_WSHADOW} \
${GLINT_WSTRICT_PROTOTYPES} \
${GLINT_WTRADITIONAL} \
${GLINT_WWRITE_STRINGS} \
${GLINT_W} \
${GLINT_EXTRA_FLAGS} \
-o /dev/null -O4 -g -c $*
splint (http://www.splint.org/) is quite excellent; I've used it one megaline codes to look for this sort of thing,
(Updated: everybody wants to be an art director.)
Although I am sure that this is not a comprehensive list of static code analysis tools, here are my impressions of some different ones that I've worked with in the past. (I work mostly with C.)
Splint: I often use Splint because it is available for many GNU/Linux distributions. It is relatively easy to work with; however, it tends to be overwhelming when operating under the strictest setting. Moreover, the sometimes-necessary use of annotations can clutter and obfuscate easily-readable code. Regardless, I suggest using it.
Uno: Uno is definitely a promising, but it is not as rigorous as Splint (by design). Instead, it focuses on the clarity and usefulness of its warnings. For me, Uno is only useful as a supplement to Splint (to clearly point out warnings hidden among the comparatively many that Splint issues).
PC-lint: I find that PC-lint is unwieldy for a proprietary program. I once used it when developing for MS-DOS and cryptic names it uses for its errors made it very difficult to use. From what I hear, there are many better products to use on MS-DOS.
Pscan: (Dead hyperlink) Pscan is great for finding format string vulnerabilities! As with Uno, I suggest using it as a supplement to Splint.
If you do not work with C, you may also want to check out: Wikipedia - List of tools for static code analysis, Inspection/Review Tools, Source/Binary Code Static Analyzers, and Source Code Security Analyzers.
How about to use a profiler and find what code is running the most, and focus in on those parts.
Maybe gprof can help out?
/Johan
Edit: Or since you talked about cleanup, invert my answer above and remove the code that never executes.