Finding unused (aka “dead”) code in Delphi

2019-02-08 13:05发布

问题:

Are there any tools that can determine if a function/procedure/method/entire class is used?

I've seen tools that can help a knowledgeable developer track down unused fragments of code (most are for languages other than Delphi) but most have a steep learning curve and/or require considerable digging to determine if a code fragment is used or not.

Delphi's smart linker purportedly does this to reduce the size of the final executable. Unfortunately what little information is given on the smart linker doesn't indicate a way to retrieve what was culled from the hurd.

Admittedly, even if it is possible to find out what the smart linker is eliminating it may be very conservative with its culling.

回答1:

Although clumsy and not global, you can examine the source code for the dots in the margin, as shown below. These are lines on which you can set breakpoints because the code hasn't been deadcode eliminated.

This happens, I believe, at the procedure level. I don't know a way to determine this at a less coarse level.



回答2:

This thread discusses removing unused units, and talks about tools like Icarus Pascal Analyzer. That tool will do all you need and more. How to "automatically" remove unused units from uses clause?



回答3:

You could also check the most commonly used commercial profiler/coverage tool, AQTime from http://www.automatedqa.com

Here's a video on features: http://www.automatedqa.com/products/aqtime/screencasts/coverage-profiling/



回答4:

You can use a Code Coverage tool to find unused code. Just run the application and execute all parts manually. The code coverage report will show which parts have not been touched. (Running the tool on the unit tests is not helpful because unused code still can have unit tests).

A free (open source) Code Coverage Tool for Delphi is available here. After running it, check for red lines in the reports, these are the lines which have not been reached.

Delphi Code Coverage is a simple Code Coverage tool for Delphi that creates code coverage reports based on detailed MAP files.

For each unit there will be a unit.html with a summary of the coverage, followed by the source marked up. Green lines were covered. Red lines were not covered lines. The other lines didn't have code generated for it. There is also a CodeCoverage_summary.html file that summarizes the coverage and has links to the generated unit reports.

Maybe the author can add a 'search for dead code' feature in a future version.



回答5:

Checkout the tools at http://www.peganza.com/ to help with some of your tasks.

Icarus is freeware and it analyzes your 'uses' clauses to allow you to remove unused references.

Pascal Analyzer is the full version which includes Icarus functionality and a ton of other tools.



回答6:

Maybe CodeHealer could help you with unused code

CodeHealer performs an in-depth analysis of source code, looking for problems in the following areas:

Audits: Quality control rules such as unused or unreachable code, use of Delphi directive names and keywords as identifiers, identifiers hiding others of the same name at a higher scope, and more. Checks: Potential errors such as uninitialised or unreferenced identifiers, dangerous type casting, automatic type conversions, undefined function return values, unused assigned values, and more. Metrics: Quantification of code properties such as cyclomatic complexity, coupling between objects (Data Abstraction Coupling), comment ratio, number of classes, lines of code, and more.



回答7:

For units, use Pascal Analyzer. You might need to use it a multiple of times.

For objects/classes that are registered in class factories (and the like), you will need to double check manually, as they will be fully compiled in. The reason for this is that the compiler doesn't know if you actually use them or not.

For methods, you need to check for the blue dots. Not very practical, so there is another way (from what I have been told when I investigate the same topic). You need to do a full build with a detailed map file enabled. Once that is done, you need to compare the source to see if there is an entry in the map file. If not, then the code is not compiled in - possibly dead code (possibly because if it is component, then it might be that you don't use that functionality).



回答8:

In the past I've compiled sources with Free Pascal using the "generate assembler" functionality, and then made some simple filter programs that operate on the source. (for this bit is useful to know that smartlinking is done using linker "section" granularity)

It sometimes gives you insights why certain things are not smartlinked out (e.g. because there is a reference in some table that might be accessed by something in an initialization)

Of course Delphi is not FPC, but when you have hints what to look for, it is a matter of looking at the dots in the margin after a Delphi compile to see if it is smartlinked or not. Likewise, if you have wonder why certain code has (not) been smartlinked out, analyzing a small example program compiled to assembler with FPC can make the reason obvious. (e.g. you find RTTI tables with a reference to it)

The FPC route allows for a systematic route to search candidates for such tests.