天天看點

我怎麼知道代碼中的哪些部分從未使用過?

本文翻譯自:How can I know which parts in the code are never used?

I have legacy C++ code that I'm supposed to remove unused code from.

我有遺留的C ++代碼,我應該從中删除未使用的代碼。

The problem is that the code base is large.

問題是代碼庫很大。

How can I find out which code is never called/never used?

如何找出從未調用/從未使用過的代碼?

#1樓

參考:https://stackoom.com/question/KCKJ/我怎麼知道代碼中的哪些部分從未使用過

#2樓

CppDepend is a commercial tool which can detect unused types, methods and fields, and do much more.

CppDepend是一個商業工具,可以檢測未使用的類型,方法和字段,并做更多。

It is available for Windows and Linux (but currently has no 64-bit support), and comes with a 2-week trial.

它适用于Windows和Linux(但目前沒有64位支援),并提供為期2周的試用版。

Disclaimer: I don't work there, but I own a license for this tool (as well as NDepend , which is a more powerful alternative for .NET code).

免責聲明:我不在那裡工作,但我擁有此工具的許可證(以及NDepend ,這是.NET代碼的更強大的替代品)。

For those who are curious, here is an example built-in (customizable) rule for detecting dead methods, written in CQLinq :

對于那些好奇的人,這裡有一個用于檢測死方法的示例内置(可自定義)規則,用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] }
           

#3樓

I had a friend ask me this very question today, and I looked around at some promising Clang developments, eg ASTMatcher s and the Static Analyzer that might have sufficient visibility in the goings-on during compiling to determine the dead code sections, but then I found this:

我今天有一個朋友問我這個問題,我環顧了一些有希望的Clang開發項目,例如ASTMatcher和靜态分析器 ,它們在編譯過程中可能具有足夠的可見性以确定死代碼部分,但後來我發現了這個:

https://blog.flameeyes.eu/2008/01/today-how-to-identify-unused-exported-functions-and-variables

https://blog.flameeyes.eu/2008/01/today-how-to-identify-unused-exported-functions-and-variables

It's pretty much a complete description of how to use a few GCC flags that are seemingly designed for the purpose of identifying unreferenced symbols!

它幾乎是一個完整的描述,說明如何使用一些看似為識别未引用符号而設計的GCC标志!

#4樓

The general problem of if some function will be called is NP-Complete.

如果将調用某個函數的一般問題是NP-Complete。

You cannot know in advance in a general way if some function will be called as you won't know if a Turing machine will ever stop.

如果某些功能被調用,您無法事先知道,因為您不知道圖靈機是否會停止。

You can get if there's some path (statically) that goes from main() to the function you have written, but that doesn't warrant you it will ever be called.

如果有一些路徑(靜态地)從main()到你編寫的函數,你可以得到,但這并不能保證你将被調用。

#5樓

One way is use a debugger and the compiler feature of eliminating unused machine code during compilation.

一種方法是使用調試器和編譯器功能,在編譯期間消除未使用的機器代碼。

Once some machine code is eliminated the debugger won't let you put a breakpojnt on corresponding line of source code.

一旦消除了一些機器代碼,調試器就不會讓你在相應的源代碼行上放置一個breakpojnt。

So you put breakpoints everywhere and start the program and inspect the breakpoints - those which are in "no code loaded for this source" state correspond to eliminated code - either that code is never called or it has been inlined and you have to perform some minimum analysis to find which of those two happened.

是以你在任何地方放置斷點并啟動程式并檢查斷點 - 那些“沒有為此源加載的代碼”狀态對應于被删除的代碼 - 要麼代碼從未被調用,要麼已被内聯,你必須執行一些最小值分析找出這兩者中的哪一個發生了。

At least that's how it works in Visual Studio and I guess other toolsets also can do that.

至少它是如何在Visual Studio中工作的,我猜其他工具集也可以做到這一點。

That's lots of work, but I guess faster than manually analyzing all code.

這是很多工作,但我想比手動分析所有代碼更快。

#6樓

It depends of the platform you use to create your application.

這取決于您用于建立應用程式的平台。

For example, if you use Visual Studio, you could use a tool like .NET ANTS Profiler which is able to parse and profile your code.

例如,如果您使用Visual Studio,則可以使用.NET ANTS Profiler之類的工具來解析和分析您的代碼。

This way, you should quickly know which part of your code is actually used.

這樣,您應該快速了解代碼的哪個部分實際使用。

Eclipse also have equivalent plugins.

Eclipse也有相同的插件。

Otherwise, if you need to know what function of your application is actually used by your end user, and if you can release your application easily, you can use a log file for an audit.

否則,如果您需要了解最終使用者實際使用的應用程式的功能,并且您可以輕松地釋出應用程式,則可以使用日志檔案進行稽核。

For each main function, you can trace its usage, and after a few days/week just get that log file, and have a look at it.

對于每個主要功能,您可以跟蹤其使用情況,并在幾天/周後擷取該日志檔案,并檢視它。

繼續閱讀