Monday 7 December 2015

Spot The Bug: The Unintentionally Reused Variable

It's time for Spot The Bug again, folks. Put your game face on.

Gotta catch those bugs!

The one that got me was an elementary error that most software developers may encounter while using a compiled language such as C++ or Java. I was using JavaScript, which is an interpreted language, and rather lax where certain things go. The code still worked, but it didn't work the right way. Whereas a compiled language would have caught it right at compilation stage.

I was trying to generate ten paragraphs containing a random number of sentences. It was a prototype content filler for a site layout test.

Here's the code.
<script>
function writearticle()
{

    for (i=0;i<10;i++)
    {
        document.write ("<p>");
        writeparagraph();
        document.write ("</p>");
    }

}

function writeparagraph()
{
    var j=Math.floor((Math.random() * 5) + 1);

    for (i=0;i<j;i++)
    {
        document.write ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
    }
}
</script>

What went wrong 

It looked simple enough, but every time I ran the function writearticle(), the browser locked up and crashed.

By rule of thumb, if there isn't an error message and your browser crashes, we look for an infinite loop in the code. And sure enough, I found it in the For loop of the writearticle() function.

Why it went wrong 

It was all in the variable i. Normally, the interpreter does not insist that variables be explicitly declared, especially if you're just going to use that variable as part of a For loop.

But I used the variable i in a For loop inside the writearticle() function, and then within the For loop, I ran the writeparagraph() function.

And the writeparagraph() function also ran a For loop using a variable named i. This was an error in scope. If I had run the writeparagraph() function outside of the writearticle() function, the variable i in each of the functions would have been treated as a separate entity. But since the writeparagraph() function was run from inside the writearticle() function, the variable i was treated as the exact same  variable i in the writearticle() function!

The writeparagraph() function defines variable j as a number between 1 and 5, and assigns i to be equal to j when the For loop ends. Thus when control is returned to the writearticle() function, i will always be a number between 1 and 5. Which also means that the condition for the writearticle() function's For loop to end - when i is 10 - is never met.

There you go - infinite loop!

How I fixed it 

I added this one line.
function writeparagraph()
{
    var j=Math.floor((Math.random() * 5) + 1);
    var i;

    for (i=0;i<j;i++)
    {
        document.write ("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
    }
}

So in the writeparagraph() function, the variable i is always explicitly declared. The interpreter will no longer equate the writearticle() function's i variable with the writeparagraph() function's i variable.

Moral of the story

Be explicit when declaring variables even when not specifically required by the language, and be mindful of variable scope. It's a good habit. Infinite loops aren't the only things that can result from a variable scope error.

Keep squashing those bugs. Keep your i out!
T___T

No comments:

Post a Comment