0

I am writing a C++ applications in the embedded area. A lot of times I think about should I use static or non-static const variable in the functions/methods? Here are my thoughts:

  1. Static constant variable eats memory while the app is running, this leads to a more memory consumption and less memory available on the device.

  2. Non-static constant variable eats memory only when the function/method is called because it will be allocated on the stack, but it will use processor a bit for allocation and initialization.

So, I decided not to use statics whenever possible. Do I do this right or at least optimal?

  • 1
    Be aware of constexpr – Basile Starynkevitch Jul 12 '17 at 8:56
  • How much RAM do you have? – CodesInChaos Jul 12 '17 at 11:15
  • Wondering why my question is marked as duplicate. We can say that "writing a good working code" is premature optimization too then. – Victor Polevoy Jul 14 '17 at 7:53
  • @CodesInChaos: it can be 4K of RAM ! – Dmitry Ponyatov Jan 17 '18 at 5:32
  • First look at MISRA C++ embedded safe code standard: it will give you some answers how to write stable C++ code for embedded. – Dmitry Ponyatov Jan 17 '18 at 5:44
6

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
  • You literally suggesting to make everything static? Even things like loop variables? – Doc Brown Jul 12 '17 at 11:12
  • 1
    @DocBrown I don't think he was referring to local variables on the stack. He is concerned about dynamic memory allocation. – Frank Hileman Jul 12 '17 at 17:39
  • Static loop variable could well be problematic as could other locals but anything with a wider scope should be. Please keep in mind that in the embedded work you tend to be short of resources which can lead to allocation failures with any dynamic content. In safety critical or high reliability work new, malloc, etc.are often forbidden by the coding standards for this very reason. – Steve Barnes Jul 12 '17 at 18:48
  • @SteveBarnes - I think a little bit of "why" with regards to "static" would turn your post into a top-notch answer. I certainly believe in pre-allocating all your memory needs but I'm not sure of the reasoning for static other than possibly to prevent stack overflows. – Dunk Jul 12 '17 at 19:24
  • @Dunk - I hope my edit helps. – Steve Barnes Jul 13 '17 at 6:28
1
  1. There is no point in premature optimizations.
  2. In c++ some statics do not use memory. In the example below maxInstances do not use memory even when compiled with -O0.

    class A { public: static size_t const maxInstances = 10; ... }

Not the answer you're looking for? Browse other questions tagged or ask your own question.