[HN Gopher] MISRA C
___________________________________________________________________
MISRA C
Author : skibz
Score : 69 points
Date : 2023-11-06 04:54 UTC (1 days ago)
(HTM) web link (en.wikipedia.org)
(TXT) w3m dump (en.wikipedia.org)
| xormapmap wrote:
| The MISRA guidelines are awful.
| AnimalMuppet wrote:
| Could 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 wrote:
| They 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 wrote:
| Exactly. 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 wrote:
| MISRA 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 wrote:
| I 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.
| Avshalom wrote:
| They're called "misery C" because it's an easy joke.
| einpoklum wrote:
| From 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), 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 wrote:
| > 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 wrote:
| > 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 wrote:
| Cross-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 wrote:
| Why do you think that believing that sizeof(int) == 4 is
| worse than believing that int32_t exists? It doesn't have
| to
| ska wrote:
| If I type doesn't exist in your toolchain, your compile
| will fail an you will know way.
|
| Converstly, incorrect assumptions about size/size/capcity
| can lead to subtle runtime bugs.
| nicoburns wrote:
| I can think of lots of cases where carelessly using int
| might cause issues. And none at all where it's actually
| better than using a different type. Aside from anything
| else, it's probably better to default to unsigned types.
|
| I'm fully willing to believe that MISRA-C contains a lot of
| silly, unnecessary rules, but IMO this isn't one of them.
| If typing out uint32_t, etc is too long, then you can
| always create an alias.
| IshKebab wrote:
| In practice the arbitrary sizing of basic C integer types
| (int, long, etc.) has proven to be extremely error prone.
| Basically it's virtually impossible to use them correctly
| (except in small examples). You don't get any portability
| benefits because it's too difficult to write code that is
| _actually_ portable across word sizes, and you get extra
| bugs when things don 't behave like you expect. There's
| basically no upside.
|
| It's much less error prone to use fixed size types,
| especially since approximately all computers are now 32 or
| 64 bit.
|
| I once lost hours on an Arduino project exactly because of
| this. I was using the SD card library, and there was an
| infinite loop bug. Turned out to be because most Arduinos
| (at the time) are 16 bit, but I was using a 32 bit one. The
| code had been written using `int` but also assumed that int
| was 16 bits!
|
| The code was _less_ portable because of the "portable" int
| sizing system. It didn't work at all with other sizes,
| whereas if it had been written using uint16_t it would have
| worked fine.
|
| You can say "well they made a mistake", but remember we're
| talking about MISRA. Avoiding mistakes is the whole point.
| ska wrote:
| > I can think of quite a few cases where using 'int' is
| fine; why is that a problem?
|
| It's a problem when your toolchain or target changes, and
| assumptions you were making (explicitly or implicitly)
| about 'int' now fail in difficult to understand ways.
| AlotOfReading wrote:
| The relevant MISRA rule (which is advisory, not mandatory)
| includes avoiding size_t, which is absolutely the correct
| type to use in a lot of pointer situations.
| MaxBarraclough wrote:
| Do you have a source for that? From a quick Google it
| doesn't seem to prohibit size_t.
|
| Rule 3-9-2 (which is only advisory) says _Typedefs that
| indicate size and signedness should be used in place of the
| basic numerical types_ , but this doesn't prohibit use of
| size_t.
|
| https://forum.misra.org.uk/thread-1130.html
| AlotOfReading wrote:
| I didn't say it prohibited size_t, only that it suggests
| avoiding it like other variable-sized types. In practice,
| compliance checkers will turn advisory rules into
| warnings, which means every usage of a size_t can
| potentially become a warning message. It's a lot of
| unnecessary noise for writing correct code.
| IshKebab wrote:
| Read his link.
| FirmwareBurner wrote:
| _> you probably have them in your head as coding guidelines
| anyway_
|
| Ha, if only. Sure, if everyone working on the project is a
| skilled C dev then yeah, but not when you're piecing together
| code form a bunch of bodyshops as it often happens in
| automotive where everything is contracted out to the lowest
| bidder to push costs down, so MISRA is there as a minimum
| common denominator to make sure that your code doesn't reach
| rock bottom in the process.
| gte525u wrote:
| FWIW - usually when interfacing with foreign code like that you
| match what the foreign code's types than convert it afterwards.
| Then add an assert [sizeof(t1) >= sizeof(int)] or better a
| static_assert.
|
| The intent isn't to make your code bullet-proof. It's to move
| towards a subset of the language with well-defined semantics.
|
| Any safety critical coding standard work I've done always had a
| waiver process for both MISRA and mccabe-like complexity
| requirements - the intent is there's always some point where
| there is diminish returns for compliance.
| NovemberWhiskey wrote:
| > _always had a waiver process for ... mccabe-like complexity
| requirements_
|
| Also known as "the one trick that your test team doesn't want
| you to know".
| lordfrito wrote:
| Reminds 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 wrote:
| > 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 wrote:
| C 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 wrote:
| The 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 wrote:
| > 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 wrote:
| Why 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 wrote:
| We 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.
| DaiPlusPlus wrote:
| > No dynamic allocation unless it can't be avoided (and
| performance/optimization is not a valid excuse).
|
| Eliminating dynamic allocation is a performance optimisation,
| I'd have thought?
| glitchc wrote:
| Such a great story! Thank you for sharing.
| time4tea wrote:
| a=a; // silence misra unused
|
| Oh the games, oh the kwalitee.
| gte525u wrote:
| Shouldn't that be (void)a;
| dfox wrote:
| clang produces explicit warning for that exact statement, while
| gcc do not.
|
| But well in embedded space there is the another question of how
| things like IAR behave, which I'm too lazy to test now.
| 0x000xca0xfe wrote:
| MISRA 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!
| ReactiveJelly wrote:
| Jeez. 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
| FirmwareBurner wrote:
| _> I am still baffled how all my colleagues just went along
| with it and never were like: Wait a second! This is awful!_
|
| They probably went along if MISRA compliance is pushed by a
| clueless manager who wants to impress a customer with "our 100%
| MISRA compliance" and who doesn't want to hear about your _'
| WHYs'_ to exceptions to the rules, then all you can do is
| blindly comply and suffer through while you look for another
| job. Ask me how I know.
| staunton wrote:
| How do you know? (Some anecdotes please?)
| 0x000xca0xfe wrote:
| Yeah, and this is exactly the problem with standards like
| MISRA C and the reason I will never work on projects like
| this ever again.
|
| When rules become more important than reality, everybody
| directly involved just stops caring.
|
| The early return rule is easy to check, but what about a
| "don't write code with a mental load so high that nobody will
| be able to understand it next year" rule?
|
| If the customer wanted actual quality, they would hire
| dedicated testers and/or write a really good testing harness.
| FirmwareBurner wrote:
| _> Yeah, and this is exactly the problem with standards
| like MISRA C and the reason I will never work on projects
| like this ever again. _
|
| I think it's unfair to point the problem as being with
| MISRA. MISRA doesn't force you to be 100% compliant with
| everything there, you're free to pick and choose what you
| think makes sense for your project and use case and to have
| your own exception. It's just a set of guidelines, that's
| it..
|
| The real problem is people(mangers) who don't understand it
| and want 100% compliance at all cost just because it sounds
| good and they feel it covers their ass ( _" nobody ever got
| fired for being 100% MISRA compliant"_ /s), instead of
| investing dev brainstorming time in pruning the list and
| having a sane review and approval process for exceptions.
|
| It's a problem with moving from engineering mentality to
| bodyshop mentality.
| bluGill wrote:
| 100% is easy to measure and report on. As soon as you
| allow even one exception it is really hard to figure out
| if the exception is really needed, or it is just a bad
| programmer being lazy at the expense of quality.
| Management should not have to figure that question out.
| FirmwareBurner wrote:
| _> it is really hard to figure out if the exception is
| really needed, or it is just a bad programmer being lazy
| at the expense of quality_
|
| That's exactly why you have (in self respecting
| companies) a sane internal standard for exceptions with
| workshops and trainings, and experienced senior devs
| review the exception requests, precisely to make sure
| it's never a lazy dev or junior.
| actionfromafar wrote:
| I guess the implied reason is something like "don't make
| functions which can accidentally leak resources". "It would
| probably help to ban early returns."
|
| NO. It won't help. At all.
| jpfr wrote:
| The recent 2023 version of MISRA C costs just a few pound as
| PDF. So I got it from $WORK. I don't have a lot of experience
| with the previous versions. But the 2023 version reads quite
| okay.
|
| It is not possible to mandate "though shall write good code"
| because it is not at all clear what that means. Instead they
| needed to come up with rules that can be checked with automated
| tools.
|
| The rules are classified as mandatory, required or advisory.
| Only the mandatory rules cannot be overridden by explicit
| documentation. As an example, "The goto statement SHOULD not be
| used" is an advisory rule. Given the bad bad spaghetti code
| that beginner programmers produce with goto, this is quite
| reasonable. Even though some code is definitely better _with_
| goto. For example to jump to some cleanup before returning.
|
| Similarly, "A function SHOULD have a single point of exit at
| the end" is an advisory rule only. The rationale for the rule
| stated in the standard is the following (slightly rephrased):
|
| 1. A single point of exit for a function is required by the IEC
| 61508 and ISO 26262 standards as part of the requirements for a
| modular approach. 2. Early returns may lead to the
| unintentional omission of function termination code. 3. If a
| function has exit points interspersed with statements that
| produce persistent side effects, it is not easy to determine
| which side effects will occur when the function is executed.
|
| I'm also a big advocate for early return. But the points from
| the rationale are valid. And I don't have a good alternative
| rule that achieves the same goal and is checkable with
| automated tools...
| 0x000xca0xfe wrote:
| That's the thing. The rationale sounds good. But where is the
| evidence?
|
| The code base followed all the rules, yet it was worse and
| had more bugs than any non-conformant code base I have ever
| seen.
|
| And teaching beginners to strictly follow rules instead of
| mercilessly rewriting and testing code until it is
| sufficiently clean and correct is the worst you can do, IMHO.
| DaiPlusPlus wrote:
| > Even though some code is definitely better with goto. For
| example to jump to some cleanup before returning.
|
| I'd have thought by-now that they'd be mandating dialects of
| C with try/finally instead of goto for error-handling.
| actionfromafar wrote:
| That's the rule that stuck with me. Because I hate it.
| bluGill wrote:
| No early return is critical to understanding and maintaining
| functions of more than 10,000 lines. (probably the limit is
| around 100 lines, but in my experience functions are either
| less than 100 lines, or more than 10,000 lines - you rarely see
| anything in the middle in the real world). I'm a firm believer
| in not writing long functions so I like early return, but
| having had to deal with 60,000 line functions early return
| makes it even harder to figure out how to get someplace or why
| you didn't.
| zik wrote:
| I honestly think that MISRA ends up creating worse code that's
| less reliable because it forces programmers into contortions to
| get even simple stuff done. It's like programming with one hand
| tied behind your back - and a lot of it seems to be for no good
| reason.
|
| I'm thoroughly convinced that MISRA was invented by someone who
| hates programmers and just wants to see them suffer for no
| reason.
|
| Can't use size_t because it's a variable sized type? Yeah,
| that's not a win.
|
| Can't do early returns to keep code clean and clear? Now we
| have to do a heap of flags and nesting, resulting in less
| maintainable code. I'm so grateful to have my code improved
| this way.
|
| Even the experts say that "deviations" are sensible and
| necessary. So what that really means is you shouldn't ever
| fully comply with MISRA because it's against common sense. And
| what does that tell you about companies which require MISRA
| compliance?
| enriquto wrote:
| Together 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_Dev...
|
| [1]https://github.com/torvalds/linux/blob/79c70c304b0b443429b2a..
| .
| FirmwareBurner wrote:
| Might 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_stan...
|
| [2]
| https://www.safetyresearch.net/Library/BarrSlides_FINAL_SCRU...
|
| [3] https://www.ipa.go.jp/publish/qv6pgp00000011mh-
| att/000065271...
| ndesaulniers wrote:
| Linux 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 wrote:
| I'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 wrote:
| How 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 Que No Los Dos? situation)
|
| https://en.m.wikipedia.org/wiki/Mutation_testing
| https://pitest.org/quickstart/mutators/
| gte525u wrote:
| Safety critical in aerospace uses MCDC as the gold standard for
| testing.
| FirmwareBurner wrote:
| MCDC is also required in automotive for the highest safety
| critical components (steering, powertrain, etc)
| maldev wrote:
| Really 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 wrote:
| > 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 wrote:
| Most of the times, not always. They sometimes don't use
| malloc or free but their own special little memory pools.
| BeetleB wrote:
| From 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).
| RealityVoid wrote:
| Yeah, so what they do is they don't use free and malloc,
| but use a bunch of buffers they free. Tadaa! We don't
| have dynamic allocation, just buffers, see? I've seen it,
| I can count in AUTOSAR systems like... 20 different hand
| spun allocators, 10 ques and 50 special little
| hierarchical state machines.
| DaiPlusPlus wrote:
| Forgive my lack of exposure to safety-critical C, but
| without dynamic allocation how does a program handle
| large state with indeterminate lifetimes? Or when you
| need a temporary buffer that's too big to live on the
| stack?
| RealityVoid wrote:
| You make the stack bigger. You might think I'm joking,
| but I'm not.
|
| Or you make it static. You can work around it just fine.
| BeetleB wrote:
| > but without dynamic allocation how does a program
| handle large state with indeterminate lifetimes?
|
| If you haven't, I strongly encourage taking a
| workshop/course on requirements engineering (not specific
| to SW nor safety). One thing that stood out is a
| requirement that says things like "indeterminate" or
| "large" are red flags. A requirement should state bounds
| on what sizes it should handle.
|
| > Or when you need a temporary buffer that's too big to
| live on the stack?
|
| Do you have an example of where this may occur in a
| safety critical system?
|
| I've forgotten the details, but many/most forbidden
| things are allowed in the code provided you have
| watchdogs for mitigation - so if things did fail it could
| safely shut down. I don't recall if dynamic allocation
| fell into that category.
| RealityVoid wrote:
| MISRA is sometimes unfairly shat on, sure, but some things do
| require you to use your brain.
|
| Regarding magic numbers, if my memory is not playing tricks on
| me, MISRA does not include 0 or 1 as magic numbers. Regardless,
| 1 is 1 regardless the number system you work in, I have never
| ever seen someone "yes, let's make 1 not be 1" (not in a sane
| way at least) and defining stuff like that for "improved
| flexibility" is an antipattern in my book. It makes code
| bigger, harder to navigate and understand. That kind of code
| does unexpected stuff, is hard to work with and has more bugs.
| The less surprises, the less indirection I get in a code base,
| the better. I also feel it makes refactoring harder not easier.
| I speak from experience, I've worked with codebases like that,
| they suck. (Hello Vector, if anyone working for them is out
| there!)
| bluGill wrote:
| #define ONE 1 is bad code.
|
| good code would be #define MAX_FOO 1 #define
| TOTAL_SUPPORTED_BAR_COUNT 1 #define STATUS_BYTE_OFFSET 1
|
| The important thing there is even though all are one we have
| both given them a unique name, and indicated why they are one.
| lordfrito wrote:
| > 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.
|
| I agree with you on magic numbers in general, but there have to
| be practical limits.
|
| I was paid to deliver tight production code that was
| performant, often interfacing with assembly because that was
| what we had to do with the cheap micro our project used. I
| wasn't worried about other number systems, it wasn't worth
| spending R&D $$$ to make the code compatible with other number
| systems. I'm not writing code that will last 100 years. I
| deliver to schedules and budgets. Your arguments strike me as a
| bit too rigid, too academic. Not practical in the real world.
|
| In my mind if (condition) num_found =
| num_found + 1
|
| is clearly superior than this MISRA version if
| (condition) num_found = num_found + ONE
|
| Because the first case is the simplest implementation,
| incredibly explicit as it. We're counting something. That's
| abundantly clear.
|
| The second case is inferior because, as a reviewer doing their
| job, I have to go and lookup what ONE actually _is_. In case
| someone defined it weird. I start thinking "Maybe it's not 1,
| maybe it's 1.0". or "maybe its fixed point like (1.0 * 256)."
|
| The moment I'm wondering what ONE is actually defined as, I'm
| no longer thinking about the code I'm reviewing. I have to
| interrupt my mental process to go find ONE, understand _that_ ,
| and then come back and pick up with what I was reviewing.
|
| This stuff matters. Clarity matters. When 1 might not be 1,
| well then I have to think harder. Compounded, all these little
| complications dilutes the quality of the code overall. And
| programmer resources and time are limited.
|
| Also, not to nitpick but your example "goto cleanup" is also
| not MISRA compliant. I'd argue that use of gotos is a greater
| sin than returning early.
|
| I'm pragmatic. I've used gotos, where it makes sense, which is
| almost never. But never say never. Gotos are _nearly always_
| bad. Early returns are useful _sometimes_. Assembly should be
| avoided _when possible_.
|
| Code is a tradeoff. When writing interrupt service routines,
| performance matters, and I found this is where I broke the
| MISRA rules the most. Because the code _had_ to be tight. That
| was the value my company brought to the customer. We could get
| out of the interrupt quick enough to guarantee deadlines in the
| rest of the code. You do this by letting yourself write complex
| code in some places, the places that matter. And you scrutinize
| those more than you do the rest of the code.
|
| MISRA (as misapplied by mid level managers) pretends the above
| statement doesn't matter.
| Krssst wrote:
| > In C, you have to be really careful with your flow control
| and memory allocations
|
| I was going to ask if an early return could still be called
| "early" if there were resources to free, but I would say error
| checking after locking an object would still qualify (releasing
| the lock being necessary).
|
| C++ helps with this with RAII.
| ribs wrote:
| MISRA 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.
| dfox wrote:
| MISRA 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).
___________________________________________________________________
(page generated 2023-11-07 23:01 UTC)