Unreachable code

From Wikipedia, the free encyclopedia

Contents

In computer programming, unreachable code, or dead code, is code that exists in the source code of a program but can never be executed.

Dead code is generally considered undesirable for a number of reasons, including:

  • If the author of the code intended the code to be executed, then there is a bug in the program.
  • If the author and maintainers of the code have overlooked the fact that it will never be executed, then time and effort may be wasted on maintaining it.

Redundant code is code that is executed but has no effect on the output from a program. Identifiers that are declared but never referenced are not included in this definition and usually go by another name such as redundant declaration.

[edit] Detecting dead code

Detecting dead code is a form of static analysis and involves performing control flow analysis to find any code that will never be executed regardless of the values of variables and other conditions at run time. In some languages (e.g. Java) unreachable code is explicitly disallowed. Naturally enough, the optimization that removes dead code is known as dead code elimination.

Code may become dead as a consequence of the internal transformations performed by an optimizing compiler (e.g., common subexpression elimination). There are probably other specialized domains that also make use of this term.

[edit] Reasons unreachable code is created

The following are some of the reasons why unreachable code may exist in source code.

During software development some programmers temporarily disable code (ie, insert constructs that prevent it being ever executed). For example, in the following code:

while (condition)
{
  foo();
  bar();
}

If we wish to temporarily disable the functionality of bar() (possibly several lines of code), a quick hack would be:

while (condition)
{
  foo();
  continue;
  bar();
}

In this example, bar() has become unreachable code (since continue means run the next iteration of the loop immediately instead of at the end of the loop). Unfortunately, sometimes changes that are intended as temporary make their way into the release version.

Other sources of unreachable code include redundant checking of exception conditions, and debugging code which has yet to be removed.

Complete functions may not be executed as they are no longer called (presumably the reason why they were written is that they used to be called), or are called only from unreachable code.

The presence of unreachable code may reveal either logical errors due to alterations in the program or significant changes in the assumptions and environment of the program (see also software rot); a good compiler should report dead code so a maintainer can think about what it means.

[edit] Detecting unreachability

Determining whether an arbitrary piece of code is unreachable code is equivalent to solving the halting problem. This means that it is not possible to correctly locate unreachable code in all cases.

In practice the sophistication of the analysis performed has a significant impact on the amount of unreachable code that is detected. For example, constant folding and simple flow analysis shows that the statement xyz in the following code unreachable:

int n = 2 + 1;
if (n == 4)
  {
  xyz
  }

However, a great deal more sophistication is needed to work out that in the following code:

double x = sqrt(2);
if (x > 2)
  {
  xyz
  }

the statement xyz is unreachable.

[edit] Unreachability vs. profiling

In some cases, a practical approach may be a combination of simple unreachability criteria and use of a profiler to handle the more complex cases. Profiling in general can not prove anything about the unreachability of a piece of code, but may be a good heuristic for finding potentially unreachable code. Once a suspect piece of code is found, other methods, such as a more powerful code analysis tool, or even analysis by hand, could be used to decide whether the code is truly unreachable.

[edit] See also

In other languages