[FYI] Check your bounds when using arrays

I know this but became lazy until a hidden bug cost me the last two days chasing up and down my code. What I wanted to share here is if you have a c-string, make sure you check whether you are overflowing it by checking it every time you are about to add to it.

Say if you have this:

char buffer[64];
int buffer_pointer=0;

Then you will fill up the buffer like:

buffer[buffer_pointer]=Serial.read();
buffer_pointer++;

in a loop. Make sure you do

if (buffer_pointer==64) Serial.println("Buffer full");

Even if you swear on your great grand father's grave that this buffer will NEVER EVER EVER fill. I will tell you a winded story if you swear instead of checking bounds.

Funny you mention this. I have a program at work that involves a lot of dynamic memory allocation. I, too was certain that all the array bounds were correct. But the program kept crashing. Iadded code to print the index and value for every array before every write to each array. I found that I was writing 8 elements into a 4 element array. Correcting that problem completely eliminated the crashing.

Moral of the story: Stay within the lines.

Id suggest that instead you explicitly check whether your array index is less than the length of the array before appending to the array - and have an 'else' clause to handle the overflow case. How you handle it is up to you, but at least make it clear in the code that the design addresses the overflow case. I prefer to declare a variable recording the length of the array, defined next to the array, and either used to define the size of the array or calculated from the array definition - not hard-coded independently of the array.

If the array is holding a c string (null terminated char array) then I also suggest that the 'length' variable be one less than the actual size of the array so that the final element is always available to null terminate the array, and I suggest you null-terminate the array each time you modify it.

(Personally, I don't like the use of 'pointer' in a variable name that is not strictly a pointer.)

Shake hands PaulS!

Mine is a bit more of “I swear this is enough space” but swearing is just not enough :wink:

The story starts with me trying to interpret data from a serial sensor. It sends a string (like R1234\r) every so often (like 6.67 times a second) so not so fast. I only need to sense it once a minute so I leave the serial buffer to fill up and the sensor’s most recent numbers are not received (no big deal, the sensed quantity won’t change much over a minute of time). So when the minute is up, I read all that serial buffer into my own buffer (caution: no bound checking because I already sworn that the cyclic Serial buffer is 64 bytes and set my buffer to 65 bytes). So it happens, a very large project I built from ground up (months of time in the making) gets wifi connectivity. Great! But it keeps messing up (very purplex, which is why I love trouble shooting, I can do a lot more swearing than usual). And I later found out that occasionally that buffer I swear will not overflow, does it but why?! I guess as slow as the sensor sends, it has a chance to catch up with me emptying the serial buffer and dumping bytes to my buffer. As I am doing that (super fast), one or two bytes just arrived and got into the cyclic Serial buffer Arduino system sets up and my program ends up reading 65 bytes and zero ending a byte that is beyond the bound of the array I set up. Quite explains why a pointer started with value 4634 (121Ah) occasionally became 4608 (1200h). So I didn’t think of the dynamic nature of the cyclic buffer and assumed a static view that it has only 64 bytes at best. Say if the reay 1-byte hardware buffer is just about to fill up with the last bit and I started emptying the cyclic buffer, that byte in the hardware buffer will be moved into the cyclic buffer before I finish reading the 64 bytes and I will ready 65 bytes. Glad that I did catch this. Tells me the good C programming rules are always correct even if it means more time and more typing. I also learned that the memory is small endian, great!