我有遗留的c++代码,我应该删除不使用的代码。问题是代码库很大。

我如何才能知道哪些代码从未被调用/从未被使用?


当前回答

我不认为它可以自动完成。

即使使用代码覆盖工具,也需要提供足够的输入数据来运行。

可能是非常复杂和昂贵的静态分析工具,如Coverity的或LLVM编译器可能会有所帮助。

但我不确定,我更喜欢手动代码审查。

更新

嗯. .不过,仅删除未使用的变量和未使用的函数并不难。

更新

看了其他人的回答和评论后,我更加坚定地认为这是不可能的。

您必须了解代码以获得有意义的代码覆盖率度量,如果您知道大量的手动编辑将比准备/运行/检查覆盖率结果更快。

其他回答

一种方法是使用调试器和编译器特性,在编译过程中消除未使用的机器代码。

一旦某些机器代码被删除,调试器就不会让你在相应的源代码行上添加断点。因此,您将断点放置在任何地方,并启动程序并检查断点——那些处于“此源未加载代码”状态的断点对应于已消除的代码——要么该代码从未被调用,要么已内联,您必须执行一些最小分析,以找出这两者中哪一个发生了。

至少这是它在Visual Studio中的工作方式,我猜其他工具集也可以做到这一点。

这需要做很多工作,但我认为比手动分析所有代码要快。

CppDepend是一个商业工具,它可以检测未使用的类型、方法和字段,以及做更多的事情。它适用于Windows和Linux(但目前不支持64位),并有两周的试用期。

免责声明:我不在那里工作,但我拥有这个工具的许可证(以及NDepend,它是。net代码的一个更强大的替代方案)。

对于那些好奇的人来说,这里有一个内置的(可定制的)检测死方法的规则示例,用CQLinq编写:

// <Name>Potentially dead Methods</Name>
warnif count > 0
// Filter procedure for methods that should'nt be considered as dead
let canMethodBeConsideredAsDeadProc = new Func<IMethod, bool>(
    m => !m.IsPublic &&       // Public methods might be used by client applications of your Projects.
         !m.IsEntryPoint &&            // Main() method is not used by-design.
         !m.IsClassConstructor &&      
         !m.IsVirtual &&               // Only check for non virtual method that are not seen as used in IL.
         !(m.IsConstructor &&          // Don't take account of protected ctor that might be call by a derived ctors.
           m.IsProtected) &&
         !m.IsGeneratedByCompiler
)

// Get methods unused
let methodsUnused = 
   from m in JustMyCode.Methods where 
   m.NbMethodsCallingMe == 0 && 
   canMethodBeConsideredAsDeadProc(m)
   select m

// Dead methods = methods used only by unused methods (recursive)
let deadMethodsMetric = methodsUnused.FillIterative(
   methods => // Unique loop, just to let a chance to build the hashset.
              from o in new[] { new object() }
              // Use a hashet to make Intersect calls much faster!
              let hashset = methods.ToHashSet()
              from m in codeBase.Application.Methods.UsedByAny(methods).Except(methods)
              where canMethodBeConsideredAsDeadProc(m) &&
                    // Select methods called only by methods already considered as dead
                    hashset.Intersect(m.MethodsCallingMe).Count() == m.NbMethodsCallingMe
              select m)

from m in JustMyCode.Methods.Intersect(deadMethodsMetric.DefinitionDomain)
select new { m, m.MethodsCallingMe, depth = deadMethodsMetric[m] }

我真的没有使用过任何工具做这样的事情…但是,就我所看到的所有答案,没有人说过这个问题是不可计算的。

这是什么意思呢?这个问题不能用计算机上的任何算法解决。这个定理(这样的算法不存在)是图灵停止问题的一个推论。

你将使用的所有工具都不是算法,而是启发式(即不是精确的算法)。他们不会给你所有没有使用的代码。

这取决于创建应用程序时使用的平台。

例如,如果你使用Visual Studio,你可以使用像. net ANTS Profiler这样的工具来解析和分析你的代码。通过这种方式,您应该很快知道实际使用了代码的哪一部分。Eclipse也有等效的插件。

否则,如果您需要知道最终用户实际使用了应用程序的哪些功能,并且您可以轻松地发布应用程序,则可以使用日志文件进行审计。

对于每个主要函数,您可以跟踪它的使用情况,并在几天/一周后获取日志文件,并查看它。

如果某个函数将被调用的一般问题是np完全的。一般来说,你无法提前知道某个函数是否会被调用,就像你不知道图灵机是否会停止一样。如果存在从main()到您所编写的函数的某个路径(静态),则可以获取,但这并不保证它将被调用。