celeron55 wrote: ↑Sun Aug 29, 2021 6:48 pm
I would often consider it fine to use dynamic allocation when you only do it once at startup, and never free anything. This implies that when changing the configured components in the UI, the only acceptable thing to do is to save the configuration and reboot. This way you begin again with a blank heap to allocate into, and can allocate different objects.
Pointers to statically allocated instances could be more robust though and I often use them myself in more complex firmware. You can use contructors to reset static instances at any time by doing something like staticFooInstance = FooClass();, which will call the constructor of FooClass just like doing new FooClass();, but instead of doing dynamic allocation places the result into the static variable. This is obvious of course, but that's part of why it's good.
One possibility would be using placement new (
https://en.cppreference.com/w/cpp/language/new). It allocates an object at a pre-allocated buffer of any type. Best to use uint32_t to have 4-byte alignment:
Code: Select all
#include <new>
static uint32_t buf[sizeof(Terminal)/sizeof(uint32_t)];
extern "C" int main(void)
{
Terminal* test = new (buf) Terminal(USART2, termCmds);
}
Of course we wouldn't be using a specific class that we can just do sizeof() on but would need to come up with an expression that determines the maximum size of classes T1, T2, T3 at compile time.
So when changing parameter "InverterType" in the event handler just call new() on the selected inverter class (and maybe delete() on the current one? - might be easier to go destructor-less).
In the Makefile we need to switch to at least c++17. Brings up a few warnings in the existing code but nothing critical.