Reason behind MISRA rule 111

I write compilers for a living, I deal with customers ranging from one man job shops to very large companies.

Standards are not about trust or enforcement they are about disciplined engineering.

w..

Reply to
Walter Banks
Loading thread data ...

Do they? Sorry, my practice differs wildly. The only tools which have ever *found* real bugs in my code were cppcheck and PREfast. Both are free, I might add. And both found bugs because they know the APIs I use. Our MISRA checker mostly makes problems because it's hard to set up and does not parse perfectly valid code (such as 'char foo[] = { "foo" }', which is valid C [ISO 9899:1999 §6.7.8(14)]). To add irony, their website claims they understand the language standards better than most developers.

Does MISRA improve code quality? People want measurable quality. Using MISRA the seemingly-usual way ("we want zero violations") is well measurable, but does not improve code quality.

§2.4 "Sections of code shall not be commented out." This forbids me to write examples in my comments ("these three functions are used with a for() loop like this: ..."). The intent of the rule is to avoid (a) old code hanging around in comments (which is indeed very annoying), and (b) to have a screenful of code which is not compiled because I don't see the comment delimiters. But the intent is not measurable. The described workaround solves neither problem. And (b) could be very easily solved using "//" comments. Alas, they are forbidden. §7.1 "Octal constants [...] shall not be used." How does my code get any better if I have to specify file permissions in hex (or with lengthy constants)? Everyone knows what mode 0755 is. But do you know what S_IRWXO is (without looking up the octal value)? §10 requires casts for almost everything. How does my code get any better when I have to write 'a = (uint8_t) (b & 255)' instead of just 'a = (b & 255)'? The observable result is just that it gets slower. §14.1 says no unreachable code. §15.3 says I need a 'default' clause in switches, even if I have already covered all possibilities. How does this go together? And §14.1 forbids me that defensive 'return 0' after a thread's 'while(1)' main loop - which means some compilers now annoy me with a warning about a missing return, and the code breaks when someone changes the loop to stop. §20.5 "The error indicator errno shall not be used." How does my code get any better when I ignore errors from 'fopen'?

MISRA is good when it encourages people to think before they type. I know MISRA doesn't want me to use macros. I also know that 90% of all compilers/optimizers explode on my codec when I use inline functions instead. So I can write you a nice paper for a deviation why I need macros here (and only here). But don't treat me like a lobotomized chimpanzee who cannot distinguish "||" and "|" operators.

Stefan

Reply to
Stefan Reuther

And that's all what's needed. You don't have to obey the rules if you can reason why they don't make sense in a particular case. That just documents you thought about it.

Look at it this way: The rules are not for you (because you know what you're doing, of course), the rules are for the engineer maintaining the code after you (because he's the one who doesn't know what you were doing).

You don't need lobotomy for that. Quite often the standard biological neural network tends to see only what you expect it to see.

Vinzent.

--
A C program is like a fast dance on a newly waxed dance floor by people carrying
razors.
   --  Waldi Ravens
Reply to
Vinzent Hoefler

I know that. Tell that the QA inquisition.

Compare , which concludes: | [...] this paper attempts to assess whether important deficiencies in | the original standard have been addressed satisfactorily. | Unfortunately, they have not and the important real to false positive | ratio is not much better in MISRA C 2004 than it was in MISRA C 1998 | and it is unacceptably low in both. [...] | | [MISRA C 2004] has not solved the most fundamental problem of MISRA C | 1998, viz. that its unadulterated use as a compliance document is | likely to lead to more faults and not less because of the fault | re-injection phenomenon first noted by [1].

Which precisely matches my observation. Still, people want "zero derivations, 100% compliance".

Actually, I haven't ever had a bug regarding to those two. (However, I already had a couple of functions where I added a comment "yes, I'm really using '|' on bools here because I want both paths", to reduce that "oops, shouldn't there be two of them" feeling.)

Which is precisely my problem with most coding standards. They don't find or prevent *practical* bugs. Yes, they make code a little nicer and more consistent, which is why I'm at least following those parts. But when I have to rewrite well-tested and perfectly working code just to get it through the checker, the coding standard has failed its goal.

Stefan

Reply to
Stefan Reuther

But you didn't answer either of the two questions I posed! What are the relative costs that you see in that *range* of "customers" and customer projects?

I'm *sure* the "coding costs" for SDI, e.g., are a tiny fraction of the total project costs, etc. Does that mean they write better code? More *efficient* coders? *Or*, that as a percentage of an incredibly large project, the costs are RELATIVELY smaller??

As are *guidelines*! The difference is *solely* "trust and enforcement"! (what is a Standard *without* the LACK of trust and IMPOSED enforcement? Don't you call that a

*guideline*?! "Advice"? "Best practices"?)
Reply to
D Yuniskis

Actually, I really *hate* the way octal is indicated in C. I much prefer the r notation. It is extensible (to other radix), unambiguous, doesn't add much clutter to the code and doesn't "magically" assign extra value to things like leading zeroes.

(I got bit by #include-ing some tables of constants that were created with leading zero padding instead of leading spaces)

Isn't there *also* a requirement that "error values" from functions be explicitly tested (e.g., malloc returning NULL)? So, test it everywhere *except* those cases where a mechanism has explicitly been created for this purpose.

(how do you code for range errors on something like pow(a,b) if you can't look at errno? do you try to detect the error in the

*domain*, instead? *try* it! :> )

But that is true of *any* "guideline". Where things go awry is when some *thing* (a "Standard") unilaterally tries to *force* (and ENforce) a behavior/practice without knowledge of the application, individual, etc.

Tools should *enable* good practices by assisting the user, not try to *force* practices that *hope* to make things better.

+42
Reply to
D Yuniskis

Here I think C overdid it. As I like readable code - especially if I am the one to read it some years into the future I use several #define.

e.g. | BITOR || OR ...

The | can be overseen very easily if the formulas are written without enough parenteses and spaces.

RK

Reply to
Reinhard Kopka

In message , Reinhard Kopka writes

I give you rule 36 from MIStRAy-C

Rule 36 Remember that and is and and or is or. The compiler can usually tell by context the difference between && & & & II & I & ~ &!

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills  Staffs  England     /\/\/\/\/
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Reply to
Chris H

Well, then add spaces when writing? I expect every C programmer to know that "||" means. But those macros break everyone's (mental and programmatical) parsers. And every second yacc parser which uses OR as the macro for a "||" token.

If you insist on words, at least use . It still breaks parsers, but at least it's standardized (and the names it defines are keywords in C++, making name clashes less likely).

Stefan

Reply to
Stefan Reuther

Agreed. But still we have that syntax and have to live with it.

And that's precisely the point why I believe ruling it out makes no sense: people have to know it anyway. You don't save any teaching effort. If you say "don't use ", you can save yourself all multi-threading teaching effort. But not if you say "don't use octal", because people will hit it by accident.

Of course I test return values where it matters. The problem is again people who want to enforce some rules, and oversee that it doesn't always matter. For an example, look at the trouble generated by the gcc function attribute "warn_unused_result" which is applied to the functions read() and write() in recent libcs.

A popular method of inter-process signalisation is a pipe, where one end writes a character to wake the other end. So I have this pipe fd, open with O_NONBLOCK, and I write a character into it: write(fd, "", 1); I don't care whether it fails. Because that means the pipe is full and the other end will wake up soon, which is what I want. This gives a warning. WHICH CANNOT BE TURNED OFF. I have to uglify my code, like this, int result = write(fd, "", 1); if (result == 0) { } to get rid of the warning. Just assigning it to a variable is not enough, because then I have a variable which was assigned but not used. Wonderful.

One of my favorite credos is "don't check for an error you don't know how to handle", which goes nicely along with the popular pow() implementations that don't set errno :-)

Stefan

Reply to
Stefan Reuther

(void) write (fd, "", 1);

wouldn't work?

Vinzent.

--
A C program is like a fast dance on a newly waxed dance floor by people carrying
razors.
   --  Waldi Ravens
Reply to
Vinzent Hoefler

Yes. So, you make a *guideline* that effectively warns you of how you can screw yourself by using/not using a particular language feature, etc. "Invest in your staff", as I've said before. *Educate* them so they know how to write better code and *care* about writing better code (instead of "doing what it takes" to silence the policeman)

Exactly. In my case, the problem was easy to spot: "Hmmm... why did this variable just get loaded with 66? The value should be much higher than that... yes, the acceleration profile (graph) shows something like 100, here. So, where did the 66 come from? Ah, '00102' isn't '102r10' but, rather, '102r8'! Need to 86 these leading zeroes..."

Exactly. Attempts to "legislate" rules force you to spend extra effort working around those rules. In the process, you either distort your code so that it is harder to read (requiring comments explaining why you did something that looks 'stupid': "To appease lint et al.") or add bugs (which is what the rules are supposedly trying to *prevent*).

In either case, you break your "flow" of thought (productivity) by having to deal with some triviality. Like MS's Mr Paperclip "reminding" you of stuff while you are trying to concentrate on getting something *done*.

I have a distinctive coding style in that I do lots of things you are told *not* to do. Whenever I do something that will raise eyebrows, I alert the reader/reviewer to that fact in my commentary and describe *why* I made that choice. This doesn't prevent someone who comes after me from tearing out all that code and replacing it with something more appropriate to his/her sensibilities. *But*, it shows that I have thought out the issue and cautions them to take similar care when/if they opt to replace/rewrite it.

For example, I might *deliberately* order the expressions in a compound conditional to exploit something I know about the data that will be encountered (i.e., if expr1 is expensive to evaluate and expr2 is often FALSE, I might deliberately say "expr2 && expr1" instead of "if expr2 { if expr1 { } }" which would make the deliberate choice more obvious). But, my commentary would deliberately draw attention to this.

"/* Here, There be Dragons */"

This seems to be the approach in much desktop software. Esp. things coded in C++ (where it seems obvious that some layer is probably throwing exceptions but the layers above aren't smart enough to deal with them and just terminate the application, instead.

Yet, MISRA doesn't *want* you to look at errno. Instead, you should try to *guess* as to whether the function is trying to (or should) signal an error!

And some PHB is going to be able to "sign off" on whether some particular set of "violations" are "acceptable"??

Hire competent people and invest in their skillsets. If you're afraid they'll take that "investment" elsewhere (i.e., quit), then make your workplace attractive enough that they don't

*want* to quit (or, hope that other firms have adopted a similar policy and you can "inherit" some of *their* "enhanced" staff losses).
Reply to
D Yuniskis

See, I'd say that the octal constants rule is the best example of where something that the tools will enforce coding style, rather than guidelines to be manually enforced, is beneficial.

Octal constants serve almost no purpose now that we've standardized on 8 bit bytes. File permissions are an extremely rare exception, and can be handled easily through something along the lines of

#define PERMISSION(owner, group, world) (((owner)

Reply to
Rob Gaddi

"Manually enforced" doesn't mean that a tool can't *detect* these things for you!

Should we prohibit: while (this = count--) { ... } (note '=' not '==')

Should we restrict ourselves to just *one* of the for(), while() or do-while() constructs? (personally, I use each in very different circumstances and my choice of which tells you something about the nature of the code that is encapsulated within)

It's easy to forget to check a denominator for zero. But, you might explicitly *want* to divide by zero. If you treat it as an error, then what recourse do you have when you want to do so?

How do you effect a "jump to 0x0000" if you refuse to allow a pointer to "0" to be dereferenced?

Should the compiler automatically append a NUL to each "series of characters" (avoiding the use of the word "string")?

All of these are "easy to make mistakes with" yet, when needed, they *do* offer value -- just not in 99.9728305% of most instances :>

Personally, I live in constant fear of trigraphs screwing me over. So much so, that I deliberately force myself to avoid double question marks *anywhere*. Fortunately, this works in my favor as doubling them in anything other than a colloquial exchange is "bad style". But, I am often tempted to issue a diagnostic like: "Shirley, we can't have run out of memory so soon??!"

[Thankfully, some compilers are sensitive to this sort of thing and catch my transgressions since catching them by *encountering* their unintended consequences is hard -- the diagnostic condition would have to take place for me to see the botched message!]

I don't see how unilaterally *prohibiting* them buys you anything more than having a tool find them and signal them as warnings. I.e., if that tool can prohibit them, then it must know how to

*find* them. Just change what the tool does in those cases. You can then choose which warnings are "deal breakers" instead of being at the mercy of whomever codified the "prohibitions".

Most non-toy compilers already emit lots of useful warnings. What's a few more (, among friends :> )?

Presumably, their authors -- and *users* -- see value in these as WARNINGS instead of HARD ERRORS. This, IMO, indicates that there is cause for allowing the user to determine the value of each of these "messages".

Reply to
D Yuniskis

For a parser, trailing radix takes more space and slightly more effort. For the programmer, trailing radix is easier to overlook.

But I agree that C's solution is unpalatable ... the compiler accepts only bases 8, 10 and 16. Using functions like strtoul() you can, in code, convert values from other bases but you have to separate the base and value and figure out what is the base yourself.

I really prefer Lisp's syntax (there are 2):

The simplified common syntax: #{C}{value} where C is a character - 'b' binary #b10100101 - 'o' octal #o245 - 'x' hexidecimal #xA5

or the general syntax: #{N}r{value} where N is a number, 2..36 ex: #2rb10100101 #8r245 #16rA5

YMMV, George

Reply to
George Neuner

I use them sometimes. For example, in electronics buffers and ports tend to come in 8-bit multiples. So we have a PLC-like thing with its I/Os numbered

0500 0501 0502 0503 0504 0505 0506 0507

0510

0511 ...

Etc.

The I/O line number gets defined and passed around as an octal constant. Pretty rare though I agree.

[...]
--

John Devereux
Reply to
John Devereux
[8> Actually, I really *hate* the way octal is indicated in C.

And *both* suffer from the fact that we don't *think* of the constants in terms of *any* "radix indication". I.e., to me, ASCII SP is "20" or "40", depending on "where I am". I don't think of "0x20" or "040" until I have to "write it down".

But the value of different radix is in expressing constants. You want to say things like: #define FLASH 0xFFFF0000 #define SECS_PER_TIMEZONE (24*60*60/24) #define PREAMBLE "\001\040\040" instead of being *forced* into "standardizing" on a single radix. I.e., How many folks would recognize 0x15180? Or, "32"?

[I miss being able to use *binary* constants (since I write lots of drivers that need to talk to I/O's)]

As you force people to express things in particular ways, solely for the sake of "standardization", you obfuscate their intent and *add* bugs (at design time and/or maintenance).

Reply to
D Yuniskis

You can use 0b binary constants in gcc, actually. Of course, being a compiler specific extension, this isn't supported by MISRA.

--
Rob Gaddi, Highland Technology
Email address is currently out of order
Reply to
Rob Gaddi

Yes, but it's an extension and not part of the language. I.e., not portable (won't work on HC11 compiler, etc.)

In a semi-portable way, you can write an m4 macro to handle it and preprocess your source. But that just gets painful...

Reply to
D Yuniskis

Of course not. The test suite even contains a test for this.

In the form it is defined ("not checking the result is either a security problem or always a bug"), this makes this a library error, a hardly useful compiler feature, and another example of mechanical style checking gone bad.

Stefan

Reply to
Stefan Reuther

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.