12 ms·
MISRA C
- lordfrito 3y agoReminds me of the period in my career I was doing contract work for automotive. I used to work in airbag, highly safety critical real-time stuff, so I knew my way around these kinds of systems. Mandate came down from customer everything was to be MISRA compliant. Which is great for about 1/2 of your code, just common sense stuff. Like int DebounceVal[NUM_DEBOUNCE_SIGNALS]; For the other half it's essentially impossible, especially when you're writing your own custom tasker/OS (really just a main loop with interrupts) with some simple system calls. The way things were done back then on small 8 and 16-bit systems. You will have serious deviations. There's just no way to disable interrupts without some assembly somewhere. The "non-programmer" types at our customer kept kicking the code back for not being MISRA compliant. So I had to go through a lot of iterations "fixing" things. Led to code that looked like this if (k > ZERO) ... n = n + ONE; tens_digit = num % TEN; hundreds_digit = num % ONE_HUNDRED; You get the picture. So code reviews really added no value, because instead of reviewing code (remember these weren't programmers) they just complained about what some automated tool was saying. After several back and forths I got so sick of things I created a file called MISRA.h to collect all the nonsense defines like this. #define ZERO 0 #define ONE 1 #define TWO 2 ... #define ONE_HUNDRED 100 As a joke I put this in the title block // MISRAble.h // (c) copyright blah blah blah Which of course their eagle eyes caught that, and so the comment itself got flagged by the customer as an open issue. Guess I deserved that one. Funny thing was that they had to track the issue, meeting by meeting, until it was closed out. I think the action item was something like "Remove inappropriate comment from MISRA.h" lol. As someone else pointed out here... LINT was the bomb. Made code so much better. Especially when you could do stuff like this switch (something) case A ... // yes I know I'm falling through to case B //lint -fallthrough case B: ... Once you got in the habit of appeasing LINT, your code was not only more readable but more explicit. Good times.
- smaudet 3y ago> Once you got in the habit of appeasing LINT, your code was not only more readable but more explicit. I get the hate, however: A) C/C++ sucks at interop. I don't mean C++01 vs C++13 vs C++15 vs C++17 vs C++19 (and good luck if your project doesn't explicitly specify which type of compiler it needs), I mean Visual Studio vs GCC vs LLVM vs 30 different build flags, compiler versions, target architectures, ABI and caller conventions, linker foibles and just generally one of the most buggy toolchains in existence. A tool like MISRA C doesn't save you from all that exactly, but having a standard at all is important _especially_ when doing security/safety stuff. In VM (Java/NET/Python/JS) world you have to worry about some library calls and maybe bytecode compatibility, the amount of stuff you don't have to think about is just staggering. In C/CPP you need to be both disciplined and explicit to safely do just about anything. B) Formally provable systems are the dream. Linter rules do wonders for catching common issues, but they don't catch real bugs very often. The downside of systems like MISRA C etc. is they install a false sense of security "oh it passed the tool so it must be good". In fact you are just _automating ignoring watching for issues_, and worse _obfuscating the code so finding issues is harder_. But this is why we all hope(d) Rust/Go would save us and produce more reliable software, more cheaply.
- lordfrito 3y agoC is a very powerful but very primitive language. Too easy to do all sorts of things you didn't intend. But C was all we had (we didn't even have C++), and we had to use it, and use it effectively to deliver production firmware that couldn't change after it was shipped. We used it, and we got good at it, and we loved it. And we hated it because we used it and loved it, and that gave us the right to hate it. Like my above example, when looking at tight (production, performant) C code, you always ask "did the programmer mean to do that?" or "was the programmer aware of the side effect" etc. Once I groked LINT, I understood that the comments which appeased LINT were also messages to us humans that the programmer had considered the side effects, etc. and that this was intended behavior. Made it easier to look at other people's code, heck even my old code, because it told me that "yeah, this was considered". Saved a lot of guess work, and allowed me to look at the meat of the code and not be distracted by the simple error stuff. Also, as much as I love C, my biggest complaint is that it should have been strongly typed from the very start. C# gets this right. You have to be very explicit about mangling things in C#. In straight C it's just too easy to mix types and mess simple stuff up. The compilers attitude is, "sure.. I'll compile that". I prefer it asking questions and complaining.
- BeetleB 3y agoThe problem wasn't MISRA, but your management. I've worked with the ISO standards for automotive. You can have exceptions to most rules as long as you have a justification that an independent auditor can agree with. Oh, and the ISO standards don't mandate MISRA. It's just one option. Also, the rules only apply where safety is relevant. If you can convincingly show that violating some rule won't affect safety, you were good to go. There are some pretty hefty rules, though. No recursion. No dynamic allocation unless it can't be avoided (and performance/optimization is not a valid excuse).
- lordfrito 3y ago> The problem wasn't MISRA, but your management. Agreed. But it was my customers management. And the customer is always right yada yada. So instead of using MISRA to help produce a better deliverable, it gets used as cudgel, a blunt instrument with which to beat programmers with, to create metrics that show the managers are effective at managing. In these cases, code quality necessarily suffers as a result. Because your resource constrained team has to spend more and more time on busywork. In my mind, LINT is a better tool than MISRA, because all tools can and will be abused by management, but some tools are more easily abused than others.
- BeetleB 3y agoWhy did your customer have access to your source code? Or was it the case that they didn't but they could access MISRA reports?
- lordfrito 3y agoWe were under contract to deliver them a working design, both hardware and software, which they would then manufacture. Basically outsourced R&D. So software was part of the deliverable. It was their product, their risk, after all. We didn't do this for long, just to pay the bills until we had our own products that were making us money.
- 3y ago
- glitchc 3y agoSuch a great story! Thank you for sharing.
- xormapmap 3y agoThe MISRA guidelines are awful.
- AnimalMuppet 3y agoCould you be more specific? Are they badly written, or are they bad at achieving the intended purpose? Or is the purpose itself a bad idea? And, whichever answer you give to that, why are they bad at it?
- cyberax 3y agoThey are called "misery C" by people in the industry for a reason. They don't help with the safety all that much, but make a lot of code just fucking ugly.
- GeorgeTirebiter 3y agoExactly. It reduced C to, almost, BASIC. Reduces available design patterns. Reduces available language features. HOWEVER: having a MISRA-C LINT which is required to run on all code that makes it into an automobile is, ultimately, a good thing. Yes, the homogenization is ugly, but it does mean that classes of errors just can't occur. The concept is great. There is also MISRA C++ of which I know almost nothing; is that any better?
- gte525u 3y agoMISRA C++ lags quite a bit relative to C++'s evolution over the last 20 years. It's closer to JSF C++ style guide.
- bee_rider 3y agoI only wrote a little MISRA-C code, but IIRC we had a process to get waivers which was fairly reasonable I think. BASIC, but with a human-driven process that bumps you back to C when necessary, with the understanding that multiple people look at the evil C-like code, actually seems like a fine language.
- einpoklum 3y agoFrom my experience, maintaining a standalone/embedded printf library - MISRA is a combination of two things: Common-sense rules, and pain-in-the-ass rules. The former are not very interesting and you probably have them in your head as coding guidelines anyway; but the latter, well, are a pain. Example: Avoiding implementation-defined types like `int` _every_where, even in places where my code doesn't care about what sizeof(int) is; or when I want to store the result of a system call which returns an int. I was able to accommodate most (?) of the MISRA rules (https://github.com/eyalroz/printf/issues/77 https://github.com/eyalroz/printf/issues/77), but mine is just a small library, so I don't know how restrictive they would be for a larger codebase. I suspect it would be painful and force you to avoid some legitimate and useful coding patterns.
- IshKebab 3y ago> Avoiding implementation-defined types like `int` _every_where Well that is the correct thing to do. I guess you can't really complain to MISRA about C being crazy.
- jjnoakes 3y ago> Well that is the correct thing to do. Is it? I can think of quite a few cases where using 'int' is fine; why is that a problem?
- archi42 3y agoCross-platform code - Is your int still 16 bits on your new CPU? Of course you know* your variable is always between 0 and 15, but the MISRA checker might not**. Today we have int16_t et al., so this is much less of an issue. *) IME "know" is often merely a "believe". **) Not sure that even if you have a MISRA checker that has a suitable inference, it is allowed to discard alarms on this kind of violation. I wrote MISRA test cases for something for a suitable powerful checker/analyzer, but I can't remember this detail anymore.
- usrnm 3y ago
- time4tea 3y agoa=a; // silence misra unused Oh the games, oh the kwalitee.
- 0x000xca0xfe 3y agoMISRA C is godawful, really bad. It is just a bunch of rules that "sound good" or are good in theory, but I doubt that they actually improve quality at all. I once worked on a gigantic code base that religiously followed the "no early return" rule. Instead of just returning an error code, everything saved flags and used nested ifs galore. The code wound along the screen like a dying snake, horizontal scrolling everywhere even with a widescreen monitor. Refactoring was utterly impossible, fixing simple bugs took months. I am still baffled how all my colleagues just went along with it and never were like: Wait a second! This is awful!
- actionfromafar 3y agoThat's the rule that stuck with me. Because I hate it.
- ReactiveJelly 3y agoJeez. I proposed to adopt some of the Joint Strike Fighter Air Vehicle rules for C++ [1] at one job, and I went through them marking each as "already in practice", "needs debate" or "I'm vetoing it" And I vetoed early return with a link to the article on railroad error handling. I don't know how it looks in C, but in C++ and Rust early returns are so much better. [1] https://www.stroustrup.com/JSF-AV-rules.pdf https://www.stroustrup.com/JSF-AV-rules.pdf
- paxcoder 3y agoI deprecate early returns (at least for happy cases). What article are you referring to?
- duped 3y agoEvery time I write an early return (which is every time) I think about my first college lab that had the rules "no global variables, one return statement per function" that if you violated you were failed for the lab. Luckily our TAs graded those and they cared about as much about those rules as everyone else. Today one is a principle at MS and the other at Google. Guess they knew how to code.
- 3y ago
- enriquto 3y agoTogether with the JPL coding standards [0], and the linux kernel coding style [1], this determines a pleasant, safe and sane subset of C. (Note: this does not mean that these rules should be followed blindly in all cases; but one should be familiar with them and understand their purpose before breaking them.) [0] https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Developing_Safety-Critical_Code https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Dev... [1]https://github.com/torvalds/linux/blob/79c70c304b0b443429b2a0019518532c5162817a/Documentation/CodingStyle https://github.com/torvalds/linux/blob/79c70c304b0b443429b2a...
- FirmwareBurner 3y agoMight I suggest better alternatives as more pleasant alternatives to the stuffy MISRA C book: - "Embedded C Coding Standard" by Michael Barr [1], CTO and co-founder of Barr Group, the guy who inspected the ECU code and testified in Toyota's unintended acceleration lawsuit [2]. Good stuff. - "Embedded System development Coding Reference guide" written by the Software Reliability Enhancement Center of Japan [3], which covers and expands on MISRA C and more. It's a joy in examples, explanations and eye-pleasing aesthetic. I love it. [1] https://barrgroup.com/sites/default/files/barr_c_coding_standard_2018.pdf https://barrgroup.com/sites/default/files/barr_c_coding_stan... [2] https://www.safetyresearch.net/Library/BarrSlides_FINAL_SCRUBBED.pdf https://www.safetyresearch.net/Library/BarrSlides_FINAL_SCRU... [3] https://www.ipa.go.jp/publish/qv6pgp00000011mh-att/000065271.pdf https://www.ipa.go.jp/publish/qv6pgp00000011mh-att/000065271...
- ndesaulniers 3y agoLinux kernel doesn't use a subset; it uses a superset of nearly every GNU C extension. Linux could only be compiled with GCC for so long due to its excessive use of GNU C extensions which tightly bound the codebase to one tool chain. (We fixed this in clang by implementing most GNU C extensions, at least the good ones). VLAs are banned, those are c99.
- smcl 3y agoI'm sorry, but you've clearly just skimmed this and haven't worked with, nor understood, the purpose of MISRA C. For starters, unless it's changed substantially since I worked with it, MISRA C forbids use of functions like malloc which rules it out for an enormous number of applications. Plus it's a little bit fuzzy in how some of the rules should be interpreted. Like there was one where it says there shouldn't be commented-out fragments of code (our response was to try to parse the lines of each comment, if they succeeded raise a MISRA-specific compile error). There were a few more weird things with MISRA C, but these were a couple that stuck with me. It's not a "sane" subset of C you can just pick up and run with. It's a narrow subset of C for a very specific use case.
- MichaelNolan 3y agoHow common is mutation testing in safely critical applications? I wonder if requiring a high mutation testing coverage would be more effective than adhering to misra C. (Though this seems like a ¿Por Qué No Los Dos? situation) https://en.m.wikipedia.org/wiki/Mutation_testing https://en.m.wikipedia.org/wiki/Mutation_testing https://pitest.org/quickstart/mutators/ https://pitest.org/quickstart/mutators/
- gte525u 3y agoSafety critical in aerospace uses MCDC as the gold standard for testing.
- FirmwareBurner 3y agoMCDC is also required in automotive for the highest safety critical components (steering, powertrain, etc)
- coumbaya 3y agoSame goes for Trains (including high speed trains) in France.
- maldev 3y agoReally sad to see so many people rail on this. Here's all the examples I've seen shitting on it and why MISRA is correct despite their objections. 1. ""no early return" rule" In C, you have to be really careful with your flow control and memory allocations. So basically ALL good C programmers and styles dictate that you use GOTO's for one location, a "cleanup" location, in which you check and free memory. So if you do if(!ptr) return; You do if(!ptr) { DEBUGLOG("Error allocation ptr");//Also prints out file, line, function etc. bRet = FALSE; goto cleanup; } Very common, and you can't ever mess up freeing memory. This is why it's used. 2. No magic numbers. Another person complains about not being able to do magic numbers. While it can get tedious, you really shouldn't. They use the most insane example of #define ONE 1. BUT, even in this case you can argue that if the requirements were changed for a base 8 or other numbers system, you could easily port the app by just changing these define macro's rather than scouring through the code. It's not that tedious, and it can make the codebase more flexible and solve issues and porting. 3. Not able to use 'int' You should always be explicit with your types. Even rust mainly makes you use sized variables. Why just do int, be specific, you may want int32. The C standard is pretty flexible with things like "long" just being bigger or the same size than "int". So porting things like this makes it robust. You also have the fact that if you do any networking or messages of any kind, this makes the datastructures easily portable since you know exactly what size.
- almostnormal 3y ago> Very common, and you can't ever mess up freeing memory. Except that where misra is applied, there often is no dynamic allocation at all.
- RealityVoid 3y agoMost of the times, not always. They sometimes don't use malloc or free but their own special little memory pools.
- BeetleB 3y agoFrom my experience in automotive, the ISO standard is against dynamic allocation if your system is classified high enough in terms of their safety levels. As an example, we weren't allowed to use the C++ string class, and had to find a "safer" string class for C++. (Not sure about MISRA - most of my experience is with the ISO standard, and MISRA is not mandated by it).
- ribs 3y agoMISRA is there as a standard for safety-critical code. Some contracts, some customers, some regulatory regimes will require compliance with MISRA, or perhaps another embedded coding standard, like AUTOSAR. Generally, your customer/regulator will allow you to deviate from the standard; you just need to document and explain the deviations. A static analysis tool like Helix QAC or Klocwork (bias: my company Perforce sells them) will capture your compilation and scan your code in detail to find deviations from the standard. You can then fix those deviations, or use the tool to document and explain them.
- phkahler 3y ago>> or perhaps another embedded coding standard, like AUTOSAR. I can deal with MISRA, it's just a safer subset of C. Most people demanding AUTOSAR compliance don't even know what AUTOSAR was created for, or the fact that those use cases never actually happen in practice. It's so fucked up I won't even work for a company producing AUTOSAR code any more. It's just a hard NO from me because it's an absolute waste of time and money.
- rcxdude 3y agoSee this (now somewhat legendary on the subreddit) comment on r/embedded regarding autosar: https://www.reddit.com/r/embedded/comments/leq366/comment/gmiq6d0/ https://www.reddit.com/r/embedded/comments/leq366/comment/gm... . You're not alone.
- dfox 3y agoMISRA C is total nonsense. If you need that then you should not be using C. Either you can just write the thing in straight assembler while observing the same set of rules and the result will be more readable (or well, COBOL which is more or less an equivalent to C with MISRA C rules) or you should use some high level language intended for that kind of application where the compiler can check for the issues that this ruleset tries to handle, which means Ada (or another application-specific weird Pascal/Modula dialect like CHILL or whatever).