4 ms·
These are somewhat dated rules, and generally too restrictive for modern safety critical development. For one thing, unbounded loops are situationally fine. The
by AlotOfReading 3y ago
These are somewhat dated rules, and generally too restrictive for modern safety critical development. For one thing, unbounded loops are situationally fine. The key distinction is that the program has to make forward progress regardless, which is not always the same thing as escaping the loop. Pool allocators have also become very common, so the complete prohibition on "dynamic allocation" is a lot more flexible now.
Many of the other rules broadly hold up though. You still want to avoid things like pointers because static analyzers are terrible at proving through them. This typically means LUTs are wrapped in the equivalent of an unsafe block though. Not ideal, and hopefully better tooling will eventually exist for these sorts of things.
- eschneider 3y agoThe problem with dynamic allocation (aside from the problem that it can fail) is that calls to malloc don't complete in a predicable time, so it's pretty much verboten in hard realtime apps. Pool allocators can (though not always are) written to return in a bounded time, so if it's created at startup, yeah, not really dynamic allocation.
- AlotOfReading 3y agoThey're not meaningfully different from the perspective of the programmer. You call a malloc-like function and get some memory back. The total dynamic memory use of the application is simply capped. You can do this even with libc malloc in a standards compliant way (e.g. Broadcom used to ship a malloc implemented as a series of pool allocators over statically initialized arenas), it's just uncommon.
- AnimalMuppet 3y agoIf you're the programmer who has to provably meet hard real time constraints, the difference matters quite a bit.
- deleted 3y ago[deleted]
- JohnFen 3y ago> You can do this even with libc malloc in a standards compliant way This is what I do in nontrivial embedded projects. It makes things easier and less error-prone to replace malloc()/free()/etc implementations directly with ones that behave as needed. And then you don't have the standard implementations sitting around waiting for a new dev to accidentally use them.
- dwohnitmok 3y ago> For one thing, unbounded loops are situationally fine. The key distinction is that the program has to make forward progress regardless, which is not always the same thing as escaping the loop. The article somewhat alludes to this, although they don't use the notion of progress that you use, which is extremely important. > This rule does not, of course, apply to iterations that are meant to be nonterminating—for example, in a process scheduler. In those special cases, the reverse rule is applied: It should be possible for a checking tool to prove statically that the iteration cannot terminate. As a further searchable term, people can look up "total functions." Total functions must either terminate (loop ends) or be productive (always make forward progress). That as many functions as possible should be total is a pretty good rule of thumb in any codebase.
- TeMPOraL 3y ago>> In those special cases, the reverse rule is applied: It should be possible for a checking tool to prove statically that the iteration cannot terminate. This part made me pause for a moment, but then it clicked, and I'm remembering the rare and unusual experience of facing a process that escaped a loop that was supposed to go on indefinitely. A software equivalent of transmission belt slipping off. Most frequently seen in video games, where it's mostly harmless - but imagining a scheduler in an embedded system quitting on me like this fills me with dread to irrational extent. > As a further searchable term, people can look up "total functions." Total functions must either terminate (loop ends) or be productive (always make forward progress). That's a new one to me. I'm not deep into more advanced flavors of functional programming, but I thought total functions are defined as terminating in finite time for all inputs. I suppose it depends on whether you consider infinite loop a successful termination in infinity or not, but personally I wouldn't, at least not when it's clear the function is plain running in circles (as opposed to asymptotically approaching a value).
- AlotOfReading 3y agoYep, it's a bit terrifying to contemplate. If you're ever unfortunate enough to do safety critical systems, you'll have to remember that you have to protect against this not only at the software level with formal methods, but also at the hardware level to ensure that e.g. a bit flip in the CPU registers or the instruction sequence as it travels from memory also doesn't violate your safety model.
- hedora 3y agoRust solves the pointer escape problem via static analysis and annotations, so that’s feeling pretty dated too. Similarly, allocation is fine with today’s large memories. You need to bound the request queue depth and the amount of memory allocated per request though. I also question the idea that safety critical code is a special class that is distinct from normal code. Buggy consumer devices lead to all sorts of deaths — after all, a one in a billion scenario is going to hit a few people per day on average — for example, look at the correlated 999 and 911 spam that hit iOS and (separately) android this week.