60

I'm currently working on a large and old C++ application that has had many developers before me. There is a lot of "dead code" in the project, classes and functions that aren't used by anyone anymore.

What tools are available for C++ to make a analysis of large code base to detect and refactor dead code? Note: I'm not talking about test coverage tool like gcov.

How do you find dead code in your project?

DVK
  • 119,765
  • 29
  • 201
  • 317
gudnithor
  • 750
  • 1
  • 6
  • 9
  • 2
    Use some kind of code coverage tool. I was going to suggest `gcov` but dunno whats available in VC. – Martin Wickman Mar 04 '10 at 14:53
  • We've used Bullseye with success. Here's a link for an evaluation copy. http://www.bullseye.com/evaluation.html – Matt Davis Mar 04 '10 at 14:55
  • This question has a great solution for gcc: [Is there a way to get gcc to warn about unused functions?](http://stackoverflow.com/questions/9091397/is-there-a-way-to-get-gcc-to-warn-about-unused-functions) – Greg Hewgill Mar 02 '12 at 03:00

8 Answers8

28

You'll want to use a static analysis tool

The main gotcha I've run into is that you have to be careful that any libraries aren't used from somewhere that you don't control/have. If you delete a function from a class that gets used by referencing a library in your project you can break something that you didn't know used the code.

Community
  • 1
  • 1
Alan Jackson
  • 5,983
  • 2
  • 29
  • 32
  • What if the dead code depends on specific user interactions at runtime? How can we eliminate code that is not used, but we only know which code is unused after runtime actions have been performed on the application by the end user? For example, compile a program, use, then based on that remove any code paths that were unused. Is there a tool for this? – trusktr Dec 17 '19 at 07:28
  • The second link is dead. – RoG Aug 27 '20 at 11:39
22

You can use Cppcheck for this purpose:

$ cppcheck --enable=unusedFunction .
Checking 2380153.c...
1/2 files checked 0% done
Checking main.c...
2/2 files checked 0% done
[2380153.c:1]: (style) The function '2380153' is never used.
  • 4
    Please do not post the same answer to multiple questions. If the same information really answers both questions, then one question (usually the newer one) should be closed as a duplicate of the other. You can indicate this by [voting to close it as a duplicate](http://stackoverflow.com/help/privileges/close-questions) or, if you don't have enough reputation for that, [raise a flag](http://stackoverflow.com/help/privileges/flag-posts) to indicate that it's a duplicate. Otherwise, be sure you tailor your answer to *this* question and don't just paste the same answer in multiple places. – elixenide Jul 14 '16 at 02:00
  • Even if other answers already specify the usage of static analyzers for this job, `cppcheck` is really easy to use for that. Of course you'll probably miss a few functions and maybe get some false positives, but it's a quick way to get a quick win with a good list of candidates. – Spidey Apr 22 '20 at 16:29
  • Beware that this check will be turned off when running cppcheck with the `-j 2` option for parallelism. Also, yes there will be false positive, I especially observed them for virtual member functions. – mxmlnkn Feb 09 '21 at 17:08
4

Caolán McNamara's callcatcher is very effectively used within the LibreOffice project (~6 MLOC) to find dead code.

phw
  • 212
  • 1
  • 12
3

I think your best bet would probably be a coverage tool. There're plenty for both *nix and windows. If you have unit tests, it's easy - if you have a low test coverage, then the uncovered code is either dead or not tested yet (you want both pieces of this info anyway). If you don't have unit tests, build your app with instrumentation provided by one of those tools, run it through some (should be all ideally) execution paths, and see the report. You get the same info as with unit tests, it will only require a lot more work.

Since you're using VisualStudio, I could provide you couple of links which you could consider using:

Neither of them is free, not even cheap, but the outcome is usually worth it.

On *nix-like platforms gcov coupled with tools like zcov or lcov is a really great choice.

Dmitry
  • 6,232
  • 1
  • 22
  • 19
  • After we've detected code coverage, how do we compile out unused code? Do any of these tools have the ability to do that? – trusktr Dec 17 '19 at 07:38
2

One approach is to use "Find All References" context menu item on class and function names. If a class/function is only referenced in itself, it is almost certainly dead code.

Another approach, based on the same idea, is to remove(comment out) files/functions from project and see what error messages you will get.

hongliang
  • 587
  • 3
  • 10
2

Nothing beats familiarity with the code. Except perhaps rigourous pruning as one goes along.

Sometimes what looks like deadwood is used as scaffolding for unit tests etc, or it appears to be alive simply because legacy unit tests exercise it, but it is never exercised outside of the tests. A short while ago I removed over 1000 LOC which was supporting external CAD model translators, we had tests invoking those external translators but those translators had been unsupported for 8+ years and there was no way that a user of the application even if they wanted to could ever invoke them.

Unless one is rigourous in getting rid of the dead wood, one will find your team maintaining the stuff for years.

Ira Baxter
  • 88,629
  • 18
  • 158
  • 311
lilburne
  • 555
  • 1
  • 3
  • 10
  • 1
    Even with pruning along the way, things slip through the cracks - theres still a very good use case for being able to find dead code globally. – ideasman42 Feb 03 '14 at 19:28
0

See our SD C++ Test Coverage.

You need to do a lot of dynamic testing to exercise the code, to make sure you hit the maximum amount of coverage. Code "not covered" may or may not be dead; perhaps you simply didn't have a test case to exercise it.

Ira Baxter
  • 88,629
  • 18
  • 158
  • 311
  • How do we compile out the code we detected to be unused? Does this tool help to do that? – trusktr Dec 17 '19 at 07:38
  • Test coverage can at best hint that code is dead; somebody has to go check, otherwise it might just be the code only runs on Dec 31 and you checked in April. You can sometimes find a tool that will detect that the code is really dead that will rip out the dead code. SD makes such a tool for Java; it outputs two things: a list of places it thinks (accurately) are dead, and a revised program in which that dead code is gone. If you agree with the dead places list, you keep the revised program. If you don't agree, then you fix a dead place to be not-dead and run the analysis again. – Ira Baxter Dec 17 '19 at 14:50
  • Ah ok, thanks! So it is doing static analysis. I'd like to do runtime testing to thoroughly test the code, gather the code coverage, then based on that remove any code paths that were unused. It may not be possible only with static analysis because things like user input may influence which code paths are reached. – trusktr Dec 19 '19 at 07:21
  • TheTest Coverage tool does not do static analysis; it collects runtime data about what got executed (by tests or any other way the exercises the code). Because it is very hard to ensure that all useful or even accessible code is executed, the test coverage tool does not tell what is dead; it tells what is unexecuted. If you are willing believe that unexecuted code is dead, then you could use that as a guide; IMHO that's unsafe. The "such a tool for Java" (meaning "a different tool thatn the test coverage tool") does do static analysis. – Ira Baxter Dec 19 '19 at 14:10
  • Oops, I somehow misread that. Thanks! My goal is to try to make a build of Chromium browser (which I believe is all C++) and remove unused code from it after testing it very well. I want to see how slim it may end up being compared to the full browser without no code clipped. – trusktr Dec 19 '19 at 17:33
-1

Although not specifically for dead code, I found the Source Navigator

http://sourcenav.berlios.de/

quite useful, although cumbersome to set up and a bit buggy. That was a year ago on Linux (Fedora).

Schwanritter
  • 119
  • 8