Shooting ones' self in the foot

G’day folks,

I’d just like to share a bug that kept me stumped for about three hours. Contemplate the following code:

class BadClass
{
public:
    BadClass();
};

BadClass::BadClass()
{
    delay(100);
}

// This will call the BadClass constructor.
BadClass aBadObject;

void setup()
{
	// This will never get called.
    pinMode(13, OUTPUT);
}

void loop()
{
	// This will never get called.
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay(1000);
}

This sketch will happily compile and be uploaded. An instance of aBadObject is allocated memory on the stack, and the BadClass() default constructor is called. The constructor then calls “delay()” - before setup() is called. I don’t know what happens on the microcontroller at this point, but nothing in the setup() or loop() gets called. You can’t blink an LED or write anything to the serial monitor.

Fascinating!

Yeah, global variables are constructed before the internal function init() is run. You could run it from your classes, however unless you override int main, it’ll run multiple times.

Most people use a begin() function in their class to call within setup. Use the constructor for simple things like a pin number, etc… but leave the Arduino specifics until setup().

It's not a bug: calling a function that depends on having initialised timers before the timers have been initialised is simply over-optimistic.

And some work-arounds

Using the heap

BadClass* p_badobject;

void setup()
{
    p_badobject = new BadClass();
}

Using pre-allocated memory and placement new. This shows how to delay construction without using heap memory.

uint8_t badclass_space[sizeof(BadClass)];
BadClass& badclass = *(BadClass*)(badclass_space);

void setup()
{
    new(badclass_space)BadClass();
}