7.4. Infinite Loops

An infinite loop is a loop that is never exited. Once the program flow enters the loop's body it cannot escape. Programmers sometimes design loops to be infinite on purpose. For example, a long-running server application like a Web server may need to continuously check for incoming connections. This checking can be performed within a loop that runs indefinitely. All too often for beginning programmers, however, infinite loops are created by accident and represent logical errors in their programs.

Intentional infinite loops should be made obvious. For example,

    while (true) 
    {
        /*  Do something forever . . . */
    }

The Boolean literal true is always true, so it is impossible for the loop's condition to be false. The only ways to exit the loop is via a break statement, goto statement, return statement (see Chapter 9), or an Environment.Exit call (see Section 5.5.6, “The Environment Class”) embedded somewhere within its body.

Intentional infinite loops are easy to write correctly. Accidental infinite loops are quite common, but can be puzzling for beginning programmers to diagnose and repair. Consider Example 7.15 that attempts to print all the integers with their associated factors from 1 to 20.

Example 7.15. Finding factors


namespace FindFactors
{
    class Program
    {
        static void Main()
        {
            //  List of the factors of the numbers up to 20
            int n = 1;
            const int MAX = 20;
            while (n <= MAX)
            {
                int factor = 1;
                System.Console.Write(n + ": ");
                while (factor <= n)
                {
                    if (n % factor == 0)
                    {
                        System.Console.Write(factor + " ");
                        factor++;
                    }
                }
                System.Console.WriteLine();  //  Go to next line for next n
                n++;
            }
        }
    }
}


It displays

1: 1 
2: 1 2 
3: 1 

and then "freezes up" or "hangs," ignoring any user input (except the key sequence Ctrl C which interrupts and terminates the running program). This type of behavior is a frequent symptom of an unintentional infinite loop. The factors of 1 display properly, as do the factors of 2. The first factor of 3 is properly displayed and then the program hangs. Since the program is short, the problem may be easy to locate. In some programs, though, the error may be challenging to find. Even in Example 7.15 the debugging task is nontrivial since nested loops are involved. (Can you find and fix the problem in Example 7.15 before reading further?)

In order to avoid infinite loops, we must ensure that the loop exhibits certain properties:

The debugger can be used to step through a program to see where and why an infinite loop arises. Another common technique is to put printing statements in strategic places to examine the values of the variables involved in the loop's control. The original inner loop can be so augmented:

while (factor <= n)
{
    System.Console.WriteLine("factor = {0}, n = {1}", factor, n);
    if (n % factor == 0)
    {
        System.Console.Write(factor + " ");
        factor++;
    }
}

It produces the following output:

1: factor = 1  n = 1
1 
2: factor = 1  n = 2
1 factor = 2  n = 2
2 
3: factor = 1  n = 3
1 factor = 2  n = 3
factor = 2  n = 3
factor = 2  n = 3
factor = 2  n = 3
factor = 2  n = 3
factor = 2  n = 3
   .
   .
   .

The program continues to print the same line until the user interrupts its execution. The output demonstrates that once factor becomes equal to 2 and n becomes equal to 3 the program's execution becomes trapped in the inner loop. Under these conditions:

  1. 2 < 3 is true, so the loop continues and

  2. 3 % 2 is equal to 1, so the if statement will not increment factor.

It is imperative that factor be incremented each time through the inner loop; therefore, the statement incrementing factor must be moved outside of the if's guarded body.


Draft updated June 30, 2013Copyright  ©2011 Richard L. Halterman