8 Common Causes of Infinite C# Loops

jos512

Jos

Posted on December 16, 2019

8 Common Causes of Infinite C# Loops

This article appeared earlier on my website.

An infinite loop makes our C# program stuck, and can even cause an application crash. Luckily, infinite loops are often easy to solve. This article shows 8 common causes and how to fix them.

Fix infinite loops: 8 causes

An infinite loop is a loop that keeps running 'forever'. These loops don't exit like regular C# loops do, but instead use up computer resources and freeze our application.

Most infinite loops are caused by either a coding or logic mistake. Some faults are pretty easy to spot, while others are more subtle.

Here are several reasons why your C# code ran into an infinite loop:

  1. Exit condition that can never be met.
  2. Condition that makes the loop to start over again and again.
  3. Loop variable that's reset to a new value inside the loop.
  4. Loop without an exit condition.
  5. Loop that doesn't change the loop variable (like a missing increment or decrement statement).
  6. Mistakingly use the increment (++) rather than decrement (--) operator (or vice versa).
  7. Incorrect logical comparison in the loop's condition (for instance, < rather than >).
  8. The continue statement in the wrong place so that it jumps over code that changes the loop variable.

If you run into an infinite loop, chances are your code has one of the above problem. Let's take a closer look at each and see what the fix is.

An exit condition that's never reached

One thing that causes an infinite loop is when our code has an exit condition, but that condition can't be reached. This is a bit tricky, because our loop does have all the required components. Yet when it runs, it doesn't stop.

Here's an example:

byte i = 0;

while (true)
{
    // ...

    Console.WriteLine($"i = {i}");
    i++;

    if (i > 275)
    {
        break;
    }
}

This intentional infinite while loop prints the value of the i variable during each loop cycle. Then it increases that variable with one (i++). When that variable is above 275, the break statement ends the loop.

Or, at least, that's the idea. In practice this loop remains stuck. The cause for this is the byte loop variable. A byte variable can hold the values 0 through 255. When its value reaches that upper level, the variable's value wraps around and starts again from zero. That makes it impossible for i to become greater than 275.

The solution is to use a loop variable of a different type, like a regular integer (int) variable:

// Fixed: loop variable now an integer
int i = 0;

while (true)
{
    // ...

    Console.WriteLine($"i = {i}");
    i++;

    if (i > 275)
    {
        break;
    }
}

A similar issue can happen when our loop variable is a floating-point value. Since float values cannot be represented exactly, a loop test like while (i != 1.1) fails when floating-point imprecision gives our loop variable a value like 1.100000000000001.

A condition that makes the loop start over and over again

An infinite loop also happens when our loop condition doesn't terminate the loop, but rather make it start over again. This can be difficult to spot: usually the code compiles fine and there's no obvious thing missing. Yet one misspelled or missing character can cause this issue.

Here's an example of that mistake:

int i = 0;

// Loop 1,000 times at most
while ((i = 1) < 1000)
{
    Console.WriteLine($"i = {i}.");

    // ...

    if (i > 125)
    {
        break;
    }
}

This while loop continues as long as the i variable is under 1000. The loop has an if statement that checks if that variable is above 125. When it is, the break statement ends the loop early.

That's the idea at least. But the loop's body doesn't change the i variable. It looks like this should be happening in the loop condition. But there we have a strange thing: the loop condition assigns i a value of 1 each time. Then it looks if that assignment returns a value under 1000 -- which it of course always is.

What the loop should do is increment i with one with each loop cycle. To implement that fix we add one character, and change i = 1 to i += 1:

int i = 0;

// Loop 1,000 times at most
while ((i += 1) < 1000)
{
    Console.WriteLine($"i = {i}.");

    // ...

    if (i > 125)
    {
        break;
    }
}

Change the loop variable to a new value inside the loop

Usually a variable controls for how long a loop should run. But if we accidentally reset that variable inside the loop, our loop doesn't get closer to its exit condition no matter how many cycles it runs.

Here's an infinite loop example of that scenario:

int i = 0;

while (i < 10)
{
    // ...

    i = 3;

    // ...

    Console.WriteLine($"i = {i}");
    i++;
}

This while loop continues for as long as the i variable is under 10. At the end of the loop's code, we increment (++) that variable with one. That should increase the variable's value all the way up to 10.

But inside the loop we also set the i variable to 3 each time. That always keeps the loop variable under 10, and the loop never ends. Since that statement doesn't seem to serve a purpose, we simply remove it to fix the problem:

int i = 0;

while (i < 10)
{
    // ...

    Console.WriteLine($"i = {i}");
    i++;
}

On a related note, it usually is a good idea to make your loop variable's name different from other variables. That way you don't mistake the loop variable for another local variable.

A loop without an exit condition

Another thing that causes a stuck infinite loop is when we don't have an exit condition. This cause is easy to spot, but unfortunately also a mistake that's quickly to make.

Here's an example:

int i = 0;

while (true)
{
    Console.WriteLine($"i = {i}");
    i++;
}

This while loop is an intentional infinite loop. That's fine, but the loop doesn't have an exit condition. So the loop keeps running forever.

Luckily, to fix this code we just have to add an exit condition. One option is to make one inside the while condition:

int i = 0;

// Fixed: add an exit condition to the loop
while (i < 10)
{
    Console.WriteLine($"i = {i}");
    i++;
}

Or we keep the true loop condition and make the loop stop with the break statement:

int i = 0;

while (true)
{
    Console.WriteLine($"i = {i}");
    i++;

    // Fixed: terminate the loop with 'break'
    if (i > 9)
    {
        break;
    }
}

A loop that doesn't change the loop variable's value

Another thing that causes an infinite C# loop is when we don't change the loop variable. This mistake is easy to make; a quick interruption and this loop component is overlooked. Luckily, the fix is easy and straightforward.

Here's how the issue can look:

int i = 0;

while (i < 10)
{
    // ...

    Console.WriteLine($"i = {i}");
}

This while loop continues as long as the i variable is under 10. However, we don't change that variable's value. And so the loop doesn't progress.

To fix this infinite loop we add a statement to the loop's code that changes that variable. Here's one option:

while (i < 10)
{
    // ...

    Console.WriteLine($"i = {i}");

    // Fixed: increase the loop variable
    i = i + 1;
}

Mixing up the increment (++) or decrement (--) operators

Sometimes our loop does change the loop variable, but in the wrong direction. One situation in which that can happen is when we accidentally swap the increment operator (++) for the decrement operator (--), or vice versa. When we do, it takes a very long time before the loop variable reaches its 'exit value'.

For example:

// Accidentally decrease, rather than increase, the loop variable
for (int i = 0; i < 10; i--)
{
    Console.WriteLine($"i = {i}");
}

This for loop has a loop variable that starts at 0. The loop itself goes on as long as that variable is under 10. We don't, however, increase that variable after each loop cycle. Instead the i-- expression decreases the variable.

One solution is to increase that variable after each loop cycle:

// Fixed: increase 'i' up to 10
for (int i = 0; i < 10; i++)
{
    Console.WriteLine($"i = {i}");
}

Or, if we meant to make a reversed loop, change the for loop header to this:

// Loop from 10 to 1
for (int i = 10; i > 0; i--)
{
    Console.WriteLine($"i = {i}");
}

Wrong logical comparison in the loop's condition

Another thing that creates an infinite loop is when our loop condition performs the wrong logical comparison. We might, for instance, use > instead of <. Or make a comparison with the wrong variable.

An example of that latter is:

int j = 0;

// ...

int i = 0;

while (j < 10)
{
    Console.WriteLine($"i = {i}");
    i++;
}

This while loop tests the j variable, while the loop itself works with the i variable. That latter variable is what Console.WriteLine() and the increment (++) statement use.

So judging from the loop's code, we probably meant to test the i variable. So to fix it we do:

int j = 0;

// ...

int i = 0;

// Fixed: loop based on the 'i' variable
while (i < 10)
{
    Console.WriteLine($"i = {i}");
    i++;
}

The continue statement at the wrong place

C#'s continue statement makes an early start of the next loop cycle. When our program executes continue, it jumps over the remaining code in the loop and revisits the loop's header.

A possible risk is that we accidentally jump over code that should run with every loop cycle. An example of that issue is:

int i = 0;

while (i < 10)
{
    // Skip all even values
    if (i % 2 == 0)
    {
        continue;
    }

    Console.WriteLine($"i = {i}");
    i++;
}

The if statement in this while loop checks if the i variable has an even value. When it has, the continue statement gives the loop an early start on the next loop cycle.

That, however, also jumps over the statement that changes the loop variable (i++). So whenever the if statement's condition tests true, the i variable doesn't change anymore and we have an infinite loop.

The solution is to move continue after the code that changes the loop variable. Or, alternatively, increase that variable before continue runs. For example:

int i = -1;

while (i < 10)
{
    // Fixed: increase variable before 'continue'
    i++;

    // Skip all even values
    if (i % 2 == 0)
    {
        continue;
    }

    Console.WriteLine($"i = {i}");
}

This ends our discussion of common causes of infinite loops. Thanks for reading and I hope you learned something new.

If you want to learn more, see all my C# programming articles.

Happy holidays!

💖 💪 🙅 🚩
jos512
Jos

Posted on December 16, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

8 Common Causes of Infinite C# Loops
csharp 8 Common Causes of Infinite C# Loops

December 16, 2019