I was puzzled by the following question: How to keep the advantage of the "static" label but still be able to debug production code on site?
Not once it happens that unintended behavior is occurring at the customer site, and only there . In many cases, having the option to perform a debug can save a lot of effort and provide a very quick response. Such a debug usually involves checking function behavior, which brings us to the "static" definition.
Static functions cannot be debugged from a debug shell, like putting breakpoints or executing it. On the other hand, defining all functions as public causes code structure and optimization grief.
I'm aware of options like compiling at least two different builds, one with static and one without, but this fits well with automation tests, not with the final production build that goes out eventually.
Will appreciated some insights from your side, mainly on how you resolved (if any) this dilemma. Or rephrasing the question to: "What is more important?"
A good discussion on "static" in C here.
I think the fundamental question is not "Do you ship with 'static' or not?", it is "Do you test exactly what you ship ?" For embedded code, if you are doing the majority of your testing on a Debug build, and then shipping a Release version compiled with different options, you are essentially shipping untested code to your customer. When you are running that close to the hardware, small changes in timing or memory access patterns (which the optimizer can easily introduce) can cause big changes in the behavior of the system.
My current strategy is to ship the Debug version, configured for as much optimization as I can stand when debugging. No Static functions, make as much state visible to the debugger as possible.
Yes, I give away some possible compiler-generated efficiencies, but as long as I ensure the Debug version is fast enough to meet its requirements, that's not a problem. And the payoff is that the code I ship is exactly the same code I've been testing with the whole release cycle - no optimizer-generated surprises.
Some debuggers can debug "static" functions. Sometimes static functions are expanded in line at the call site, though, which makes the debugger's job difficult, and some debuggers just give up.
(Inline expansion at the call site is not actually a property specific to "static", it's just that compilers are more likely to do this because they "know more" about the function—specifically, that the name is not visible outside the current translation unit, so the function's code can be omitted entirely if all its calls are expanded in-line.)
It was once common to use a macro:
#ifndef STATIC
# define STATIC static
#endif
...
STATIC void somefunc() { ... }
and then turn the macro into "nothing" for debug builds. That works pretty well, but it's even better to find a debugger smart enough to handle static functions even when they are expanded inline.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With