For loop through array causing infinite loop

236 views Asked by At

I have a piece of code that is supposed to flush an array of characters when the enter key is pressed, only the code is looping infinitely and I can't figure out why.

There is a character array that gets a new character every time a key is pressed. When the enter key is detected, the following code gets executed to flush the character array with '\0' characters before generating a new line on the screen:

int main()
{
    char i;
    char c;
    char buffer[80];
    i = 0;
    c = 0;

        while (c = bgetchar())
        {
            if (c == 13)
            {
                for (i = i; i >= 0; i--)
                {
                    buffer[i] = '\0';
                }
            }
            else
            {
                buffer[i] = c;
                i++;
            }
        }
}

The i gets incremented in the main loop every time a character gets pressed (other than an enter (ASCII 13)). The character is also added to buffer[]. That code is not shown here, though I can reproduce it. Needless to say, even if that code were improperly incrementing the i, the loop should end when i hits 0 (and i should hit 0 at some point given the decrement).

So in theory, on having an enter pressed, if there are 5 characters on the line (and no backspaces), buffer[] elements 0-4 will have the characters, and i will be equal to 5. The loop in the code should replace elements 5 to 0 with '\0' characters. Starting with element 5 is admittedly unnecessary, but it shouldn't cause the behavior I've been experiencing.

That behavior is that the loop runs endlessly. Right now I've been able to verify this by using my putchar function to print a character every time the loop is run. Now I suppose I could write another function to enable me to print the value of i as well, and I would probably obtain the answer to my question. Also, for what it's worth, the infinite loop happens when I turn this loop into the equivalent "while" loop.

I just wanted to make sure there isn't something obvious that would be causing infinite loop behavior here. Sorry if this is a stupid question. Thanks for any help. The program is being run as a raw binary in 16 bit real mode. I'm compiling from bcc to as86 to the final binary.

Edit: After doing some more debugging, I confirmed that i is going into the loop with the correct positive value (based on the number of characters in the array, e.g., i = 7 if 7 characters). While in the for loop, however, i alternates between a value of -1 and -2 ad infinitum. Since that makes no sense based on i's entry value (or based on the loop's condition), is there any chance this is some kind of memory or register issue?

Final edit: the issue appears to have been the >= condition causing i to go negative. For some reason, this caused an infinite loop even though the condition in the for loop checks for a negative i. Thanks for all of the help.

1

There are 1 answers

2
chux - Reinstate Monica On

For some reason, this caused an infinite loop even though the condition in the for loop checks for a negative i.

"the condition in the for loop checks" is true, yet the condition is not checked everywhere it is needed.


At least one problem: attempting buffer[-1] = c; which is undefined behavior (UB) - which can include an infinite loop.

When the input after (c == 13) is not 13, code attempts this UB.

    while (c = bgetchar()) {
      if (c == 13) {
        for (i = i; i >= 0; i--) {
          buffer[i] = '\0';
        }
        // now i == -1;
      } else {
        // No protection here that `i` is on the 0..79 range
        buffer[i] = c;
        i++;
      }
    }

for (i = i; i >= 0; i--) is questionable as its first buffer[i] = '\0'; is on something that was not set in the else's buffer[i] = c; i++; part.

I suspect OP needs

        // for (i = i; i >= 0; i--) {
        for (i = i; i > 0; ) {
          // buffer[i] = '\0';
          buffer[--i] = '\0';
        }

char i; is unusual. I'd expect a fixed signed type, not a char which might be signed or unsigned. Perhaps unsigned char i (after above fix) or an idiomatic size_t i; for array indexing.