我有遗留的c++代码,我应该删除不使用的代码。问题是代码库很大。
我如何才能知道哪些代码从未被调用/从未被使用?
我有遗留的c++代码,我应该删除不使用的代码。问题是代码库很大。
我如何才能知道哪些代码从未被调用/从未被使用?
当前回答
Mark as much public functions and variables as private or protected without causing compilation error, while doing this, try to also refactor the code. By making functions private and to some extent protected, you reduced your search area since private functions can only be called from the same class (unless there are stupid macro or other tricks to circumvent access restriction, and if that's the case I'd recommend you find a new job). It is much easier to determine that you don't need a private function since only the class you're currently working on can call this function. This method is easier if your code base have small classes and is loosely coupled. If your code base does not have small classes or have very tight coupling, I suggest cleaning those up first.
接下来将标记所有剩余的公共函数,并制作一个调用图,以找出类之间的关系。从这棵树上,试着找出树枝的哪一部分看起来可以修剪。
这种方法的优点是你可以在每个模块的基础上进行测试,所以当你的代码库损坏时,你很容易通过单元测试,而不会有很长一段时间。
其他回答
真正的答案是:你永远无法真正确定。
至少,对于重要的情况,你不能确定你已经得到了全部。考虑以下来自维基百科关于不可达代码的文章:
double x = sqrt(2);
if (x > 5)
{
doStuff();
}
正如维基百科正确指出的那样,一个聪明的编译器也许能够捕捉到这样的东西。但是考虑一下修改:
int y;
cin >> y;
double x = sqrt((double)y);
if (x != 0 && x < 1)
{
doStuff();
}
Will the compiler catch this? Maybe. But to do that, it will need to do more than run sqrt against a constant scalar value. It will have to figure out that (double)y will always be an integer (easy), and then understand the mathematical range of sqrt for the set of integers (hard). A very sophisticated compiler might be able to do this for the sqrt function, or for every function in math.h, or for any fixed-input function whose domain it can figure out. This gets very, very complex, and the complexity is basically limitless. You can keep adding layers of sophistication to your compiler, but there will always be a way to sneak in some code that will be unreachable for any given set of inputs.
还有一些输入集是永远不会被输入的。输入在现实生活中没有意义,或者在其他地方被验证逻辑阻塞。编译器没有办法知道这些。
这样做的最终结果是,虽然其他人提到的软件工具非常有用,但您永远无法确定您捕获了所有内容,除非您随后手动检查代码。即便如此,你也无法确定自己是否错过了什么。
恕我直言,唯一真正的解决方案是尽可能保持警惕,使用自动化,尽可能地重构,并不断寻找改进代码的方法。当然,这样做是个好主意。
我不认为它可以自动完成。
即使使用代码覆盖工具,也需要提供足够的输入数据来运行。
可能是非常复杂和昂贵的静态分析工具,如Coverity的或LLVM编译器可能会有所帮助。
但我不确定,我更喜欢手动代码审查。
更新
嗯. .不过,仅删除未使用的变量和未使用的函数并不难。
更新
看了其他人的回答和评论后,我更加坚定地认为这是不可能的。
您必须了解代码以获得有意义的代码覆盖率度量,如果您知道大量的手动编辑将比准备/运行/检查覆盖率结果更快。
我通常找没用的东西的方法是
确保构建系统正确地处理依赖项跟踪 设置第二个监视器,使用全屏终端窗口,运行重复构建并显示第一个满屏的输出。watch "make 2>&1"倾向于在Unix上做到这一点。 在整个源代码树上运行查找和替换操作,添加“//?”“在每一行的开头 通过删除相应行中的"//?"来修复编译器标记的第一个错误。 重复操作,直到没有错误。
这是一个有点漫长的过程,但确实能得到很好的结果。
我真的没有使用过任何工具做这样的事情…但是,就我所看到的所有答案,没有人说过这个问题是不可计算的。
这是什么意思呢?这个问题不能用计算机上的任何算法解决。这个定理(这样的算法不存在)是图灵停止问题的一个推论。
你将使用的所有工具都不是算法,而是启发式(即不是精确的算法)。他们不会给你所有没有使用的代码。
If you are on Linux, you may want to look into callgrind, a C/C++ program analysis tool that is part of the valgrind suite, which also contains tools that check for memory leaks and other memory errors (which you should be using as well). It analyzes a running instance of your program, and produces data about its call graph, and about the performance costs of nodes on the call graph. It is usually used for performance analysis, but it also produces a call graph for your applications, so you can see what functions are called, as well as their callers.
这显然是对页面其他地方提到的静态方法的补充,它只会有助于消除完全不使用的类、方法和函数——它不会帮助找到实际调用的方法内部的死代码。