Dead Code Identification (C++)

Dead code identification (C++)

You'll want something along the lines of QA-C++ (http://www.programmingresearch.com/QACPP_MAIN.html), also see http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis for similar products.

You're looking for a static code analysis tool that detects unreachable code; many coding guidelines (such as MISRA-C++, if I'm not mistaken) require that no unreachable code exists. An analysis tool geared specifically to enforce such a guideline would be your best bet.

And you'll like be able to find other uses for the tool as well.

Dead code detection in legacy C/C++ project

You could use a code coverage analysis tool for this and look for unused spots in your code.

A popular tool for the gcc toolchain is gcov, together with the graphical frontend lcov (http://ltp.sourceforge.net/coverage/lcov.php).

If you use gcc, you can compile with gcov support, which is enabled by the '--coverage' flag. Next, run your application or run your test suite with this gcov enabled build.

Basically gcc will emit some extra files during compilation and the application will also emit some coverage data while running. You have to collect all of these (.gcdo and .gcda files). I'm not going in full detail here, but you probably need to set two environment variables to collect the coverage data in a sane way: GCOV_PREFIX and GCOV_PREFIX_STRIP...

After the run, you can put all the coverage data together and run it through the lcov toolsuite. Merging of all the coverage files from different test runs is also possible, albeit a bit involved.

Anyhow, you end up with a nice set of webpages showing some coverage information, pointing out the pieces of code that have no coverage and hence, were not used.

Off course, you need to double check if the portions of code are not used in any situation and a lot depends on how good your tests exercise the codebase. But at least, this will give an idea about possible dead-code candidates...

Why can't dead code detection be fully solved by a compiler?

The dead code problem is related to the Halting problem.

Alan Turing proved that it is impossible to write a general algorithm that will be given a program and be able to decide whether that program halts for all inputs. You may be able to write such an algorithm for specific types of programs, but not for all programs.

How does this relate to dead code?

The Halting problem is reducible to the problem of finding dead code. That is, if you find an algorithm that can detect dead code in any program, then you can use that algorithm to test whether any program will halt. Since that has been proven to be impossible, it follows that writing an algorithm for dead code is impossible as well.

How do you transfer an algorithm for dead code into an algorithm for the Halting problem?

Simple: you add a line of code after the end of the program you want to check for halt. If your dead-code detector detects that this line is dead, then you know that the program does not halt. If it doesn't, then you know that your program halts (gets to the last line, and then to your added line of code).


Compilers usually check for things that can be proven at compile-time to be dead. For example, blocks that are dependent on conditions that can be determined to be false at compile time. Or any statement after a return (within the same scope).

These are specific cases, and therefore it's possible to write an algorithm for them. It may be possible to write algorithms for more complicated cases (like an algorithm that checks whether a condition is syntactically a contradiction and therefore will always return false), but still, that wouldn't cover all possible cases.

Automated Dead code detection in native C++ application on Windows?

Ask the linker to remove unreferenced objects (/OPT:REF). If you use function-level linking, and verbose linker output, the linker output will list every function it can prove is unused. This list may be far from complete, but you already have the tools needed.

Finding dead code in a large C++ legacy application

You'll want to use a static analysis tool

  • StackOverflow: What open source C++ static analysis tools are available?
  • Wikipedia: List of tools for static code analysis

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.

Find out which code is never called in C++ project in Visual Studio 2012

Short answer: Visual Studio does not support this1.

The code analysis checkers that can find uncalled functions are available for managed (i.e. .NET) code only, e.g. CA1811: Avoid uncalled private code.

Static analysis of C++ code is a lot more difficult, and there are only a handful of Code Analysis for C/C++ Warnings related to unused/redundant/unreachable code:

  • C6235: "(<non-zero constant> || <expression>) is always a non-zero constant"
  • C6236: "(<expression> || <non-zero constant>) is always a non-zero constant"
  • C6237: "(<zero> && <expression>) is always zero. <expression> is never evaluated and may have side effects"
  • C6239: "(<non-zero constant> && <expression>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?"
  • C6240: "(<expression> && <non-zero constant>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?"
  • C6259: "labeled code is unreachable: (<expression> & <constant>) in switch-expr cannot evaluate to <case-label>"
  • C6269: "possible incorrect order of operations: dereference ignored"
  • C6285: "(<non-zero constant> || <non-zero constant>) is always a non-zero constant. Did you intend to use the bitwise-and operator?"
  • C6286: "(<non-zero constant> || <expression>) is always a non-zero constant. <expression> is never evaluated and may have side effects"
  • C6287: "redundant code: the left and right sub-expressions are identical"
  • C6288: "Incorrect operator: mutual inclusion over && is always zero. Did you intent to use || instead?"
  • C6289: "Incorrect operator: mutual exclusion over || is always a non-zero constant. Did you intend to use && instead?"
  • C6294: "Ill-defined for-loop: initial condition does not satisfy test. Loop body not executed"
  • C6313: "Incorrect operator: Zero-valued flag cannot be tested with bitwise-and. Use an equality test to check for zero-valued flags"
  • C6316: "Incorrect operator: tested expression is constant and non-zero. Use bitwise-and to determine whether bits are set"
  • C6319: "use of the comma-operator in a tested expression causes the left argument to be ignored when it has no side-effects"

All of those rules indicate either a bug, or point to redundant code, that is never executed. The list applies to code analysis rules implemented in Visual Studio 2017. Previous versions of Visual Studio may not provide checkers for all of them.


1 This is true up to and including Visual Studio 2017, the most current release at the time of writing.



Related Topics



Leave a reply



Submit