EmbeddedRelated.com
Forums

Reason behind MISRA rule 111

Started by vikasvds May 12, 2011
Vinzent Hoefler wrote:
> Stefan Reuther wrote: >> 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) { } > > (void) write (fd, "", 1); > > wouldn't work?
Of course not. The test suite even contains a test for this. <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509> 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
On Wed, 18 May 2011 06:28:46 -0700, D Yuniskis
<not.going.to.be@seen.com> wrote:

>Hi George, > >On 5/17/2011 3:19 PM, George Neuner wrote: > >[8<] > >>> Actually, I really *hate* the way octal is indicated in C. >>> I much prefer the<value>r<radix> 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. >> >> For a parser, trailing radix takes more space and slightly more >> effort. For the programmer, trailing radix is easier to overlook. > >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 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. > >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).
That's why I like Lisp's generalized radix syntax - just by looking at the number, it is clear that it is "unusual" in some way and it should be closely examined. I've used the Lisp syntax for a number of DSL compilers I've written and I've never heard anybody complain that it was weird or hard to understand. Personally I can't remember ever having a reason to use constants in bases other than 2, 10 or 16 ... but my non-decimal uses always have been limited to bit masks. I also hate octal and the only times I ever have used it have been for setting file permissions from the shell in Unix (back when chmod took only a single octal argument). George
Hi George,

On 5/19/2011 5:51 PM, George Neuner wrote:

>> [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). > > That's why I like Lisp's generalized radix syntax - just by looking at > the number, it is clear that it is "unusual" in some way and it should > be closely examined. I've used the Lisp syntax for a number of DSL > compilers I've written and I've never heard anybody complain that it > was weird or hard to understand. > > Personally I can't remember ever having a reason to use constants in > bases other than 2, 10 or 16 ...
What?? No sexagesimal support?? :>
> but my non-decimal uses always have been limited to bit masks.
I use hex for things like K, M, G, etc. (instead of their "marketing" versions -- which end in zeroes :> ) as well as for physical addresses.
> I also hate octal and the only times I ever have used it have been for > setting file permissions from the shell in Unix (back when chmod took > only a single octal argument).
In code, I use octal primarily for character constants. I.e., \010 is easier to recognize than a "BS" manifest constant. An early employer used to push "split-octal" (0xFFFF -> 377377) for Z80 programming by arguing that it was easier to "hand assemble" code using octal because, for many instructions, you could synthesize an opcode by memorizing "register identifiers" and "instruction types", etc. IMO, a perfect example of misplaced priorities ("Why should I risk MISremembering an opcode when I can have the *machine* generate the code for me???")
On 5/19/2011 10:55 PM, D Yuniskis wrote:
> I use hex for things like K, M, G, etc. (instead of their > "marketing" versions -- which end in zeroes :> ) as well as
Grrr... s/zeroes/decimal zeroes/
> for physical addresses.
On Thu, 19 May 2011 22:55:51 -0700, D Yuniskis
<not.going.to.be@seen.com> wrote:

>Hi George, > >On 5/19/2011 5:51 PM, George Neuner wrote: > >><snip> >> I also hate octal and the only times I ever have used it have been for >> setting file permissions from the shell in Unix (back when chmod took >> only a single octal argument). > >In code, I use octal primarily for character constants. >I.e., \010 is easier to recognize than a "BS" manifest >constant. > >An early employer used to push "split-octal" (0xFFFF -> 377377) for >Z80 programming by arguing that it was easier to "hand assemble" >code using octal because, for many instructions, you could synthesize >an opcode by memorizing "register identifiers" and "instruction >types", etc. IMO, a perfect example of misplaced priorities >("Why should I risk MISremembering an opcode when I can have the >*machine* generate the code for me???")
Hmm. I like hex well enough but since I worked a lot with octal (pdp-11) many years ago, I am comfortable with it. However, there is a nifty procedure that works by hand well, if you are lost on a deserted island somewhere and only have sand and your fingers to work conversions. (There are times, you know.) It uses octal. Sometimes, when I convert something from hex to decimal without a calculator around, I first convert to octal and perform one of the below algorithms. Similarly, at times when converting from some decimal number into hex, I may first convert it to octal (see below) and then quickly translate that over to hex. Anyone care to explain why the algorithms below work at all and are "symmetrical?" CONVERSION OF DECIMAL TO OCTAL (0) Prefix the number with "0." Be sure to include the radix point. It's an important marker. (1) Double the value to the left side of the radix, using octal rules, move the radix point one digit rightward, and then place this doubled value underneath the current value so that the radix points align. (2) If the moved radix point crosses over a digit that is 8 or 9, convert it to 0 or 1 and add the carry to the next leftward digit of the current value. (3) Add octally those digits to the left of the radix and simply drop down those digits to the right, without modification. (4) If digits remain to the right of the radix, goto 1. CONVERSION OF OCTAL TO DECIMAL (0) Prefix the number with "0." Be sure to include the radix point. It's an important marker. (1) Double the value to the left side of the radix, using decimal rules, move the radix point one digit rightward, and then place this doubled value underneath the current value so that the radix points align. (2) Subtract decimally those digits to the left of the radix and simply drop down those digits to the right, without modification. (3) If digits remain to the right of the radix, goto 1. For example, 0.4 9 1 8 decimal value +0 --------- 4.9 1 8 +1 0 -------- 6 1.1 8 +1 4 2 -------- 7 5 3.8 +1 7 2 6 -------- 1 1 4 6 6. octal value Let's convert it back: 0.1 1 4 6 6 octal value -0 ----------- 1.1 4 6 6 - 2 ---------- 9.4 6 6 - 1 8 ---------- 7 6.6 6 - 1 5 2 ---------- 6 1 4.6 - 1 2 2 8 ---------- 4 9 1 8. decimal value Jon
Stefan Reuther wrote:

> Vinzent Hoefler wrote: >> Stefan Reuther wrote: >>> 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) { } >> >> (void) write (fd, "", 1); >> >> wouldn't work? > > Of course not. The test suite even contains a test for this. > <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25509>
Yes. Why did I even ask? Vinzent. -- A C program is like a fast dance on a newly waxed dance floor by people carrying razors. -- Waldi Ravens
Stefan Reuther wrote:

> Vinzent Hoefler wrote: >> Stefan Reuther wrote: >>> 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). >> >> 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. > > I know that. Tell that the QA inquisition.
;)
> Compare <http://www.leshatton.org/Documents/MISRA_comp_1105.pdf>, which > concludes: > | > | [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].
Something like that is also my concern. As an example, if tasking is forbidden for safety reasons, solutions to problems that are naturally solved by using tasking, tend to become more complex and thus have a bigger potential for errors.
> Which precisely matches my observation. Still, people want "zero > derivations, 100% compliance".
Which is, of course, complete nonsense.
>>> But don't treat me like a lobotomized >>> chimpanzee who cannot distinguish "||" and "|" operators. >> >> You don't need lobotomy for that. Quite often the standard biological >> neural network tends to see only what you expect it to see. > > 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.)
I wasn't talking about writing the code. I was talking about reading it.
> Which is precisely my problem with most coding standards. They don't > find or prevent *practical* bugs.
They avoid constructs that are statistically proven to fail more often than others. As I tried to say already, that doesn't mean this doesn't just open a whole new can of worms introducing a lot new possibilities of doing it wrong - just in some other way. Vinzent. -- A C program is like a fast dance on a newly waxed dance floor by people carrying razors. -- Waldi Ravens
Hi there,

Vinzent Hoefler wrote:
> Stefan Reuther wrote: >>>> But don't treat me like a lobotomized >>>> chimpanzee who cannot distinguish "||" and "|" operators. >>> >>> You don't need lobotomy for that. Quite often the standard biological >>> neural network tends to see only what you expect it to see. >> >> 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.) > > I wasn't talking about writing the code. I was talking about reading it.
At least I'm well-conditioned enough to immediately question a construct having just "|" in a boolean context. Hence the comments.
>> Which is precisely my problem with most coding standards. They don't >> find or prevent *practical* bugs. > > They avoid constructs that are statistically proven to fail more often > than others.
Problem is, I don't see any evidence that MISRA does that. We're doing C++. MISRA C++ outlaws functions that return *this or a reference parameter. That is, it outlaws all implementations of iostreams. It outlaws <stdio.h> (use <cstdio> instead), which means there's no longer a well-defined way to get the declaration of POSIX 'fileno' or 'fdopen'. Of course, it also outlaws errno, to encourage code like std::FILE* fp = std::fopen("file", "rb"); if (fp == NULL) { printf("something bad happened, but I don't tell you what\n"); } (needless to say, all practical C++ers I know agree that NULL is bad style in C++.) It also outlaws strcpy, memcmp, etc., because they might be accidentally used on a wrong buffer or without a null check. By the same argument, we'd have to outlaw addition, multiplication and division as well, because they might be accidentally used on a wrong operand. Neither of these has any specific track record for our product. The only single problem source sticking out is signed/unsigned problems, of which we had a handful: '(-20)/2U' has an unexpected result. Of course, our rule checker does not find that (gcc does, with an increadibly high false-positive rate). Other than that, most defects were algorithmic, not language problems. Stefan
Stefan Reuther wrote:

> Vinzent Hoefler wrote: >> Stefan Reuther wrote: >>>>> But don't treat me like a lobotomized >>>>> chimpanzee who cannot distinguish "||" and "|" operators. >>>> >>>> You don't need lobotomy for that. Quite often the standard biological >>>> neural network tends to see only what you expect it to see. >>> >>> 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.) >> >> I wasn't talking about writing the code. I was talking about reading it. > > At least I'm well-conditioned enough to immediately question a construct > having just "|" in a boolean context. Hence the comments.
Well, that's surely a plus of having to work in only one language mostly, but when you're forced to adapt your mind from Python to Perl to Ada, back to Java and then to C again, conditioning the mind for each potentially questionable construct of every one of those languages is not that easy. (Of course, not all have the same criticality level, yet conditioning the mind for slopiness in one case and strict rules in another seems even harder.)
>>> Which is precisely my problem with most coding standards. They don't >>> find or prevent *practical* bugs. >> >> They avoid constructs that are statistically proven to fail more often >> than others. > > Problem is, I don't see any evidence that MISRA does that.
Which part? The statistics or the failures? ;)
> We're doing C++. MISRA C++ outlaws functions that return *this or a > reference parameter. That is, it outlaws all implementations of > iostreams. It outlaws <stdio.h> (use <cstdio> instead), which means > there's no longer a well-defined way to get the declaration of POSIX > 'fileno' or 'fdopen'.
Maybe original MISRA wasn't intended for systems which even had I/O. ;)
> Neither of these has any specific track record for our product. The only > single problem source sticking out is signed/unsigned problems, of which > we had a handful: '(-20)/2U' has an unexpected result. Of course, our > rule checker does not find that (gcc does, with an increadibly high > false-positive rate). Other than that, most defects were algorithmic, > not language problems.
Playing devil's advocate, this is a sure sign of MISRA helping you in the development, by making it harder for the "easy" bugs to creep in, leaving you only the hard ones to concentrate on. Mission accomplished. :) And I am not trying to argue _for_ the MISRA rules here, I a just trying to point out why they exist. Again, if anybody thinks MISRA will make the code safer just by obeying the rules, they are mistaken. The human part is still the important one. We, as truly responsible coders don't need those rules, the rules are always there for the other 80% who make the silly mistakes. ;) I remember the last talk with my boss: B: "So what are you currently doing?" M: "Still at refactoring the $horrible_stuff, should be finished by today. One can say, I completely rewrote it by now." B: *raises eyebrows* "So it needs to be tested before?" M: *question mark in my face* "Errm, what answer do you expect now? - Yes, of course, it needs to be tested." I am human, I did, I do and I will make errors and no f*cking rules will ever be able to change that. Vinzent. -- A C program is like a fast dance on a newly waxed dance floor by people carrying razors. -- Waldi Ravens
Vinzent Hoefler wrote:
> Stefan Reuther wrote: >>>> 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.) >>> >>> I wasn't talking about writing the code. I was talking about reading it. >> >> At least I'm well-conditioned enough to immediately question a construct >> having just "|" in a boolean context. Hence the comments. > > Well, that's surely a plus of having to work in only one language mostly, > but when you're forced to adapt your mind from Python to Perl to Ada, back > to Java and then to C again, conditioning the mind for each potentially > questionable construct of every one of those languages is not that easy.
I do less Pascal than I used to do, but I'm switching from C to C++ to Assemblers to Perl to Lisp to Javascript to Lua to Shell, that's not an issue :)
>> We're doing C++. MISRA C++ outlaws functions that return *this or a >> reference parameter. That is, it outlaws all implementations of >> iostreams. It outlaws <stdio.h> (use <cstdio> instead), which means >> there's no longer a well-defined way to get the declaration of POSIX >> 'fileno' or 'fdopen'. > > Maybe original MISRA wasn't intended for systems which even had I/O. ;)
Indeed, many of the rules make much more sense if you have an engine control unit in mind, not an infotainment device with a megapixel screen and a few Gigs of flash.
>> Neither of these has any specific track record for our product. The only >> single problem source sticking out is signed/unsigned problems, of which >> we had a handful: '(-20)/2U' has an unexpected result. Of course, our >> rule checker does not find that (gcc does, with an increadibly high >> false-positive rate). Other than that, most defects were algorithmic, >> not language problems. > > Playing devil's advocate, this is a sure sign of MISRA helping you in > the development, by making it harder for the "easy" bugs to creep in, > leaving you only the hard ones to concentrate on. Mission accomplished. :)
How does MISRA come into play here? For the code I have statistics about, we still managed to avoid most of it :-) Right now, I'm just seeing I have to add things, like casts for every other assignment, which makes it harder to see the forest for the tree. I'm not complaining about adding '{' for 'if', and I'm only half complaining about having to use 'int_fast16_t' instead of 'int' (which have precisely the same semantics, but the practical problem is that many C/C++ developers don't realize that), but I'm complaining about p[0] = static_cast<uint8_t>(v & 255); p[1] = static_cast<uint8_t>((v >> 8) & 255); which just doesn't add value, just noise. And, in particular, I'm getting grumpy when having to change older, perfectly working and tested code, adding the potential for new bugs, just to get it through a checker which has already proven by example that it itself has bugs. Stefan