34

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?

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Chris
  • 9,209
  • 16
  • 58
  • 74

6 Answers6

28

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). (2023-03-10: Support for --combine was removed by 2012 — it has long not been an option to GCC.)

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_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_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_EXTRA_FLAGS} \
    -o /dev/null -O4 -g -c $*
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
15

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.

ConcernedOfTunbridgeWells
  • 64,444
  • 15
  • 143
  • 197
11

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

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

  2. 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).

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

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

  • PC-Lint comments are strange to me - some of the best documentation I've ever seen. It *is* unwieldy due to large number of options and errors - but IMO that's the nature of the beast. Unless you want someone else's definition of what to check/ignore. – Steve Fallows Jan 05 '09 at 12:20
  • @Steve: I must've missed the documentation. I've corrected the post so as to not mislead anyone. Thank you. –  Jan 05 '09 at 19:12
6

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. ;-)

Dan Fego
  • 13,644
  • 6
  • 48
  • 59
3

splint (http://www.splint.org/) is quite excellent; I've used it on megaline codes to look for this sort of thing,

(Updated: everybody wants to be an art director.)

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
0

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.

Johan
  • 20,067
  • 28
  • 92
  • 110