当我写C代码时,我只使用编辑器和gcc。我想知道是否有人能够建议一个好的简单工具,用来查找未使用的变量、函数声明和可能进行一些优化。
有人知道一个好的工具吗?
当我写C代码时,我只使用编辑器和gcc。我想知道是否有人能够建议一个好的简单工具,用来查找未使用的变量、函数声明和可能进行一些优化。
有人知道一个好的工具吗?
正如 Dan Fego 所指出的那样,GCC 能够捕获未使用的变量和未使用的静态函数。通常情况下,它无法找到未使用的外部函数,因为它通常一次只处理一个源文件。
GCC(v4.3.2)有数百甚至数千个选项。其中一个可能有用的选项是“(2023-03-10:对 --combine
”以组合源文件(只要您不习惯在不同的源文件中放置相同的函数或变量名称)。--combine
的支持已于 2012 年被移除——GCC 已经很长时间没有这个选项了。)
选项“--help
”会告诉您更多信息;选项“--help=optimizers
”和“--help=warnings
”分别提供了几百行输出。警告包括:
-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
补充:这是一个名为glint
的脚本,我用它来清理我的代码。它相当古老,因此第一行没有使用'#!/bin/sh
'标记,并且使用'$*
'而不是'"$@"
',这两个问题都应该得到解决,但都不需要紧急处理。请注意,即使GCC 4.x不再支持'-fwriteable-strings
'选项,它仍然支持'-Wwrite-strings
'选项,并且具有价值。
这个脚本演示了只需很少的工作,就可以从现有工具中获得很多好处。你可以配置它使用的几乎每个选项,尽管主要是通过环境而不是命令行进行配置。当然,你可以在命令行中添加额外的警告选项;但你无法删除预定选项,除非通过环境进行设置。但这没问题;这些选项是基于良好的原因而默认选择的。现在,我可能会设置 'GLINT_ANSI=-std=c99
' 或者修复脚本;由于我编码时遵循 glint
强制执行的标准,所以最近没有经常使用它。 (注意,'-o /dev/null
' 表示你一次只能处理一个文件;这是一个修补的捷径!)
: "@(#)$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 $*
虽然我确定这不是一个全面的静态代码分析工具列表,但以下是我过去使用过的一些不同工具的印象。(我主要使用C语言。)
Splint:我经常使用Splint,因为它适用于许多GNU/Linux发行版。它相对容易使用;但是,在最严格的设置下操作时,它往往会让人感到不知所措。此外,有时必须使用注释,这可能会使易于阅读的代码变得混乱和难以理解。尽管如此,我仍建议使用它。
Uno:Uno绝对是一个有前途的工具,但它不像Splint那样严格(出于设计考虑)。相反,它专注于其警告的清晰度和实用性。对我来说,Uno只有作为Splint的补充才有用(以便清楚地指出隐藏在Splint发出的相对较多警告中的警告)。
PC-lint:我发现PC-lint对于专有程序来说过于笨重。我曾经在为MS-DOS开发时使用过它,它使用的加密名称使其非常难以使用。据我所听,有许多更好的产品可用于MS-DOS。
Pscan:(无效链接)Pscan非常适合查找格式字符串漏洞!与Uno一样,我建议将其作为Splint的补充使用。
如果你不使用C语言,你也许想要查看以下内容:Wikipedia - 静态代码分析工具列表, 检查/审查工具,源代码/二进制代码静态分析器, 以及源代码安全性分析器。
如果你使用-Wall参数运行gcc编译器,它会捕捉到你提到的一些问题,比如未使用的变量(也许是未使用的函数)。就优化而言,我不担心,因为通常情况下编译器足够聪明,能够进行有意义的优化。只需避免使用可怕的算法就好了。;-)
splint(http://www.splint.org/)非常出色;我已经在大型代码中使用它来查找这种问题,
(更新:每个人都想成为艺术总监。)
你考虑使用分析器来查找哪些代码运行最频繁,集中精力优化这些部分。
也许gprof可以帮助你解决问题?
/Johan
修改:或者,根据你谈到的清理操作,反转我的上述答案并删除从未执行过的代码。