Maketober Day 21: Null Discoveries

pixels.png

It turns out that nothing is important. Programs need a way of explicitly denoting that something is empty of meaningful content. C++ uses the value NULL. [I did have this awesome idea for a nerdy T shirt with the slogan “HULL != NULL” which I thought would be a great way of bigging up the local area, but I digress].

Anyhoo, my lovely sprite library uses a linked list of sprites that can be added to a frame for display. Each sprite contains a link to the next one in the list. The “next sprite” link last Sprite in the list contains the value NULL to indicate that there are no more sprites. I like this because there are no constraints on the number of Sprites I an put in a Frame. I can just keep adding them if I want more. The frame contains a variable that refers to the first sprite in the list and when I want to work on all the sprites I just start at the first one and then get each one in turn.

class Sprite
{
public:
    Frame* frame;
    void update();
    Sprite* nextSprite;
};

This is an extract from the Sprite class header. You can see the nextSprite reference. Note that C++ uses the * character to denote that a variable is a reference.

class Frame
{
public:
    Sprite * sprites;
};

This is an extract from the Frame class. Now, when I want to update all the sprites I can use this:

Sprite* currentSprite = sprites;

while (currentSprite != NULL) {
    currentSprite->update();
    currentSprite = currentSprite->nextSprite;
}

The loop starts at the beginning of the list and works through them, updating each one. Good stuff. I ran this code in my ESP8266 device and it worked a treat. Much happiness. Then I ran it in my ESP32 device and it exploded. Much unhappiness. These are the worst kinds of bugs. The ones that are just not supposed to happen.

After a bit of head scratching I worked out what was going wrong. Turns out I’d done something stupid. When I make a new Sprite I have to make sure that the nextSprite reference is set to NULL. Otherwise my update function will head off trying to update sprites that don’t exist. Which will end badly. I’d not done this. In C++ if you create something you just get the space. It is not set to any sensible value.

Friendly languages like C# will automatically set sensible initial values to variables. It just so happened that in the ESP8266 version the nextSprite references had been set to NULL even though I’d not done it. So the program worked. However, in the ESP32 version they references just pointed at random pieces of memory which turned out the a recipe for “kaboom” when the program tried to follow them.

Moral of story: make sure that when you make a new something you set it to a sensible value. Sometimes you can get away with this, but not always.