This is actually the worst thing to do because you never know what resources will be needed in all cases meaning that your code can crash in the real world when it was fine in tests. It also means that if you try to debug with an ICE specific memory addresses do not map to specific functions or variables which is a nightmare.
The best practice in the embedded world is to make everything static and initially const then only relax the const on those things that you have to.
You should also, at least while debugging set optimisations to 0 (off).
This means that:
- When you have your image you know exactly how much space it needs.
- All methods and variable have absolute addresses which allows for debugging with tools such as an ICE, (in circuit emulator).
- If it turns out that your code will not fit into the available space on the target system then you can consider saving some space, (at the cost of some speed), by removing some of the static modifiers, (the map file will help you identify those that are using the most space and the profiler results those that are use the least). You might, for example, have some large chunks that are only used during initialisation or only in debug mode that can have the static removed without undue negative impact.
A little explanation
What the keyword static
actually is and does:
static
is what is known as a storage modification instruction.
- It instructs the compiler, linker & locator to pre-allocate the storage location as opposed to dynamically allocating it.
- It also modifies the initialisation of local items, if they are initialised when declared, they are initialised at load time not each time a function is entered. So if a function contains a declaration
static int counter = 0
and increments that counter by 1 on each call the initialisation then counter will grow with each call, (without static it would never get above 1).
- As with anything
static
has plus and minus sides:
- The use of static usually makes code run faster, (since the entry to a function or method does not require allocation of memory on the stack or heap) and read/write operations are accessing a specific known address rather than having to look up a stack/heap location (direct addressing vs indirect). PLUS
- There may a slight increase in the initial load time, (in embedded code this is normally very small). MINUS
- In embedded programming, since the actual location of items is determined at build time, this would be compile, link, locate, hardware tools such as an In Circuit Emulator, (ICE), can let you examine the values, state etc., of the code while it is running with little impact on the execution speed, (unlike a debugger which usually has a major impact on the speed). PLUS
- Since all resources are pre-allocated your resources must always be at least the maximum required. This is both PLUS/MINUS
- You cannot get away with a lower amount of memory than the total required which pushes up your requirements MINUS
- You will never encounter a situation where performing a sequence of operations in one order or with one set of values crashes the program and not in others. PLUS
- Since you know at build time if you are exceeding available resources you can either upgrade the required hardware requirements or optimise your code to reduce the required storage. PLUS
- Local values persist between calls so you can easily implement things like counters without having global scope variables PLUS
- Local values persist between calls so you need to remember to explicitly reset them, (not in the declaration), MINUS
- If just about everything has been declared as static your heap & stack requirements go down considerably so getting some resource savings, PLUS
constexpr