我有遗留的c++代码,我应该删除不使用的代码。问题是代码库很大。
我如何才能知道哪些代码从未被调用/从未被使用?
我有遗留的c++代码,我应该删除不使用的代码。问题是代码库很大。
我如何才能知道哪些代码从未被调用/从未被使用?
当前回答
如果你使用g++,你可以使用这个标志-Wunused
根据文档:
Warn whenever a variable is unused aside from its declaration, whenever a function is declared static but never defined, whenever a label is declared but not used, and whenever a statement computes a result that is explicitly not used.
http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html
编辑:这是另一个有用的标志-Wunreachable-code根据文档:
This option is intended to warn when the compiler detects that at least a whole line of source code will never be executed, because some condition is never satisfied or because it is after a procedure that never returns.
其他回答
我不认为它可以自动完成。
即使使用代码覆盖工具,也需要提供足够的输入数据来运行。
可能是非常复杂和昂贵的静态分析工具,如Coverity的或LLVM编译器可能会有所帮助。
但我不确定,我更喜欢手动代码审查。
更新
嗯. .不过,仅删除未使用的变量和未使用的函数并不难。
更新
看了其他人的回答和评论后,我更加坚定地认为这是不可能的。
您必须了解代码以获得有意义的代码覆盖率度量,如果您知道大量的手动编辑将比准备/运行/检查覆盖率结果更快。
如果你使用g++,你可以使用这个标志-Wunused
根据文档:
每当变量未使用时发出警告 除了它的声明,无论何时 函数被声明为静态的,但是 从来没有定义,每当一个标签 声明但未使用,并且每当a 语句计算的结果为 明确没有使用。
http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html
编辑:这里是另一个有用的标志-Wunreachable-code 根据文档:
此选项用于在编译器检测到至少一整行源代码永远不会执行时发出警告,因为某些条件永远不会满足,或者因为它在一个永远不会返回的过程之后。
更新:我在遗留的C/ c++项目中发现了类似的主题死代码检测
GNU链接器有一个——cref选项,用于生成交叉引用信息。你可以通过-Wl,——cref从gcc命令行传递它。
例如,假设foo。O定义了一个符号foo_sym,也在bar.o中使用。然后在输出中你会看到:
foo_sym foo.o
bar.o
如果foo_sym限制为foo。O,那么你不会看到任何额外的目标文件;后面会跟着另一个符号:
foo_sym foo.o
force_flag options.o
现在,从这里我们不知道是否使用了foo_sym。它只是一个候选:我们知道它是在一个文件中定义的,而没有在其他任何文件中使用。Foo_sym可以在foo中定义。O和用于那里。
那么,你该怎么处理这些信息呢
执行一些文本修改,以识别限制在一个目标文件中的这些符号,生成候选列表。 进入源代码,给每个候选对象提供带有静态的内部链接,就像它应该有的那样。 重新编译源代码。 现在,对于那些真正未使用的符号,编译器将能够警告,为你精确定位它们;你可以删除它们。
当然,我忽略了其中一些符号是故意不使用的可能性,因为它们是为动态链接而导出的(即使在链接可执行文件时也可能出现这种情况);这是一种更微妙的情况,你必须了解并明智地处理。
对于未使用的整个函数(和未使用的全局变量),GCC实际上可以为您完成大部分工作,前提是您使用GCC和GNU ld。
编译源代码时,使用- function-sections和-fdata-sections,然后链接时使用-Wl,——gc-sections,——print-gc-sections。链接器现在将列出所有可以删除的函数,因为它们从未被调用,以及所有从未被引用的全局函数。
(当然,你也可以跳过——print-gc-sections部分,让链接器无声地删除函数,但将它们保留在源代码中。)
注意:这只会发现未使用的完整函数,它不会对函数中的死代码做任何事情。在活函数中从死代码调用的函数也将被保留。
一些c++特有的特性也会导致问题,特别是:
Virtual functions. Without knowing which subclasses exist and which are actually instantiated at run time, you can't know which virtual functions you need to exist in the final program. The linker doesn't have enough information about that so it will have to keep all of them around. Globals with constructors, and their constructors. In general, the linker can't know that the constructor for a global doesn't have side effects, so it must run it. Obviously this means the global itself also needs to be kept.
在这两种情况下,虚函数或全局变量构造函数使用的任何东西都必须保留。
另外需要注意的是,如果您正在构建一个共享库,GCC中的默认设置将导出共享库中的每个函数,导致只要链接器就会“使用”它。为了解决这个问题,你需要将默认值设置为隐藏符号而不是导出(例如使用-fvisibility=hidden),然后显式地选择你需要导出的导出函数。
如果你使用g++,你可以使用这个标志-Wunused
根据文档:
Warn whenever a variable is unused aside from its declaration, whenever a function is declared static but never defined, whenever a label is declared but not used, and whenever a statement computes a result that is explicitly not used.
http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html
编辑:这是另一个有用的标志-Wunreachable-code根据文档:
This option is intended to warn when the compiler detects that at least a whole line of source code will never be executed, because some condition is never satisfied or because it is after a procedure that never returns.