Arduino crashes if Serial.Begin() is not called in the Setup() function

Hello World,

I wrote a Version of the classic QBASIC Gorillas for the Arduino Uno using the TVOut library.

Everything worked fine until I changed the code to reinitialize after a player has won the game
so that the next round could start.

The program does start a new round, draws the new city and the players,
waits for the input of Angle and Speed and as soon as the player confirms the Speed the Uno crashes.

So I thought that I forgot to reinitialize some global variables and added "Serial.Begin(9600);" to the Setup() function in order to check my variables and debug the sketch.

And the problem disappeared... :o

I changed NOTHING except adding "Serial.Begin(9600);"!

There is not a single call to any other Serial methods and yet the bug is gone and the game works perfectly fine.
And if I remove "Serial.Begin()" the bug is there again...

Any advice, ideas or suggestions would be much appreciated!

Am I the only one who can't see any code?

Well, I have no idea what part of the code is the problem.
Should I post the entire sketch (about 1100 lines)?

This is the programming section of the forum.
What do you think you should do?
(Apart from reading the posting guidelines)

redeagle:
Any advice, ideas or suggestions would be much appreciated!

Such behaviour is typical for programs that create buffer overflows, perhaps by writing (or reading) array variables outside the array bounds.

Small changes create a slightly differenet RAM layout, and the mistake with the buffer overflow may or may not lead to a failure.

jurs:
perhaps by writing (or reading) array variables outside the array bounds.

Sir, you are a genius!

I double checked my sketch for array operations that may be outside the array's bounds.

Found one that is a local variable of a function and gets filled with data in a for loop.
And the iterator gets equal to the array size + 1...

The funny thing is I remember I did that intentionally because otherwise the array would always be empty at its last position wich led to other bugs.

I could now fix that problem by making this array a global variable.
But I dont undestand why thats necessary.

Is there a difference between local and global variables when it comes to filling arrays?

Just that different data gets clobbered. One really nasty thing is that local variables are created on the stack. depending on the arduino stack frame, return addresses might go there too, and get wiped out by your off-by-one error.

Allright, I think I figured out what the real problem is.

The Arduino Reference says the following:

" Note that when declaring an array of type char, one more element than your initialization is required, to hold the required null character. "

Is it possible that this also applies to arrays of type byte?

Because when I increased the size of my byte array by one and didn't initialize it's last element it all worked fine.
Besides that they are both 8 Bit variables, "byte" is just the unsigned version of "char" right?

If thats the case, I think this should be added to the reference because it is confusing for newbs like myself and can introduce some really nasty bugs.

Making it global turned out to be a red hering because it just changed the random garbage that occured when trying to read or initialize the null character.

Delta_G:
I think that trying to dissect your problem without seeing your code is pointless.

Amen.

redeagle:
And the problem disappeared... :o

I changed NOTHING except adding "Serial.Begin(9600);"!

If you overwrite memory by exceeding an array the behaviour is then undefined. Adding or subtracting code may make the problem appear to go away.

Please post your code so this isn't some hypothetical discussion.

Please use code tags.

Read this before posting a programming question

How to use this forum

redeagle:
Is there a difference between local and global variables when it comes to filling arrays?

There are two main differences between 'global' and 'local' variables: Initialization and lifetime.

'global' variables:

  • are initialized to zeros at start of the programm automatically (if not initialized different)
  • are living all the time while the program is executing

'local' variables:

  • are NOT initialized to zeros at start of the function automatically
  • will have pure random contents at start of the function (if not initialized different)
  • are only living while the function is executing

So non-initialized 'local' variables may have a pure random contents each time the function is entered. And these variables do not use RAM all the time, but only while the function is running. And the lifetime of such 'local' variables is limited to the execution time of the function: Function finished ==> local variable vanished. So if you set local variables to some value, finish the function and call the same function again later, the local variables will NOT have kept their values, but the values may have changed randomly.

redeagle:
Allright, I think I figured out what the real problem is.

The Arduino Reference says the following:

" Note that when declaring an array of type char, one more element than your initialization is required, to hold the required null character. "

Is it possible that this also applies to arrays of type byte?

No, it does not apply to byte arrays and it even not apply to every char array. It only applies to char arrays that are to be used as 'string' and with the AVR LIBC string functions. C-strings will have a finalizing null character at the end, they are nullterminated strings. So the string "Hi" will need 3 characters: 'H', 'i' and '\0'.

'local' variables:

sp. " 'local' non-static variables: "

AWOL:
sp. " 'local' non-static variables: "

Yes, of course. Local 'static' variables are the same as global variables:

  • they are initialized to zero before the program starts executing
  • they live all the time while the program is executing
  • they take RAM all the time while the program is executing

First of all, thank you very much for your constructive input!

Second, forget the nonsense I wrote before and have a look at this:

void drawcity()
{ 
  byte buildingheight[13];
    
  for(byte i=1;i<13;i++)
  {
    buildingheight[i] = random(8,36);
  }
  buildingheight[2]=buildingheight[3];
  buildingheight[10]=buildingheight[11];
  
  for(byte buildingnum = 12;buildingnum != 0;buildingnum--)
  {
    byte buildingxpos = (buildingnum*9) + (buildingnum -2);
    byte currentheight = 96-(buildingheight[buildingnum]*2) - 1;
    
    for(byte linenum = buildingheight[buildingnum];linenum!=0;linenum--)
    {
      byte linepos = 96 - ((linenum*2)+1);
      TV.draw_row(linepos,buildingxpos,buildingxpos-8,1);
    }

    TV.draw_row(95,buildingxpos,buildingxpos-8,1);
    
    byte columnpos = buildingxpos;
    for(byte columnnum = 5;columnnum!=0;columnnum--)
    {      
      TV.draw_column(columnpos,currentheight,95,1);
      columnpos = columnpos - 2;
    }
  }
}

The culprit was "byte buildingheight[13]".

The problem was obviously caused by my weird drawing algorythm, which only works if the number of the building is bigger than zero and therefore requires an array that is bigger by one than the actual number of buildings since arrays are zero indexed... facepalm :sweat_smile: :sweat_smile: :sweat_smile:
Please excuse the extent of my stupidity! :cold_sweat:

If you never played Gorillas and have a hard time imagening what I mean by "building" or "city",
the image generated by this code looks like that:


The height of the buildings is generated randomly every new round...

Next time I'll check my code twice before wasting everyone's precious time!
And if I get really desperate I will post the code immediately and wont try to describe the problem in general terms.

redeagle:

  byte buildingheight[13];

for(byte i=1;i<13;i++)
 {
   buildingheight[i] = random(8,36);
 }

If you define an array with 13 elements, the array index is going from buildingheight[0] to buildingheight[12].

If you would do a for loop over all indexes in the array you would start with an index of '0':

  for(byte i=0;i<13;i++)

The array index with the C/C++ programming language always starts with 0.