EmbeddedRelated.com
Forums

C and MISRA, blues... (arithmetic shifts)

Started by Nils April 24, 2008
Steve at fivetrees wrote:
> "Chris H" <chris@phaedsys.org> wrote: >
... snip ...
> >> However as with all things there are a few exceptions where got >> is the cleanest solution. In those cases you need to deviate and >> be able to stand up in court in 3 years time with your deviation. > > Sorry, but I disagree. There are always - ALWAYS - logically- > equivalent structured alternatives to goto, which will not bite > your ass anywhere near as badly.
Those equivalents are not free. General implementation requires the addition of flag variables. This was proven about 50 years ago. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section. ** Posted from http://www.teranews.com **
In message <HJWdncqgGLWTgYjVnZ2dneKdnZydnZ2d@pipex.net>, Steve at 
fivetrees <steve@NOSPAMTAfivetrees.com> writes
>"Chris H" <chris@phaedsys.org> wrote in message >news:IuwkdBEGJtEIFA4t@phaedsys.demon.co.uk... >> However as with all things there are a few exceptions where got is the >> cleanest solution. In those cases you need to deviate and be able to >> stand up in court in 3 years time with your deviation. > >Sorry, but I disagree. There are always - ALWAYS - logically-equivalent >structured alternatives to goto, which will not bite your ass anywhere near >as badly.
Not so. There are no absolutes. There are occasions when the goto is useful. Not often which is why MISRA-C bans goto. It you think you have one of the few odd places where it is needed then deviate.
>> Intestinally the "goto" is bad" came from a paper by Dykstra (not Wilco >> :-) and AFAIK no one has really challenged it but just taken it as read. I >> know some people are doing some work into it to see if it really is that >> bad. > >Ignoring the "intestinally": you're kidding! > >I've said this elsewhere, but the acid test is: if you can't look at a >section of code and know how you got there, WARNING. Therein is the danger >of goto. You say that people are seriously questioning this?
Yes. And these people spend their lives doing code analysis and looking at errors. The problem is "everybody knows" goto is bad... no one has actually shown any solid evidence that it is. Anecdotal yes but mathematical, statistical etc evidence: no. I have seen some discussions by Les Hatton on this.
>No. 2 or 3 years back I had to review the code of a certain engineer who was >not subject to normal peer review on the basis of his, errr, "adherence to >open-source methods". Turned out this was a smokescreen. His main() was over >2000 lines long, and was peppered with gotos. Summary - he was a crap coder. >I see this a lot - crap coders are crap coders, period.
I couldn't agree more (but please don't mention "open-source" it gets the religious nutters going)
>There are good >reasons for objecting to goto - Dijkstra was no fool. Those who use goto >simply don't understand the subject very well.
Actually those who are saying there is no proof that goto is bad understand more than you and I put together. They spend their lives on this sort of thing. Whilst everyone has (should have) a gut feeling that go to is bad there is no empirical evidence as there is for other things. I would be delighted if you could provide some. Your anecdote above is just that. Not solid evidence. Goto CAN be used safely. However those who would use it safely tend not to use it at all. Those who do use it do not use it well. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
In message <4815392F.5A73CD1E@yahoo.com>, CBFalconer 
<cbfalconer@yahoo.com> writes
>Steve at fivetrees wrote: >> "Chris H" <chris@phaedsys.org> wrote: >> >... snip ... >> >>> However as with all things there are a few exceptions where got >>> is the cleanest solution. In those cases you need to deviate and >>> be able to stand up in court in 3 years time with your deviation. >> >> Sorry, but I disagree. There are always - ALWAYS - logically- >> equivalent structured alternatives to goto, which will not bite >> your ass anywhere near as badly. > >Those equivalents are not free. General implementation requires >the addition of flag variables. This was proven about 50 years >ago.
That was not the problem. In some cases to remove a goto the resulting structure is horribly convoluted and unreadable. It was readability and elegance of design. However these situations are few and far between -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Chris H wrote:

> Whilst everyone has (should have) a gut feeling that go to is bad there > is no empirical evidence as there is for other things. I would be > delighted if you could provide some. Your anecdote above is just that. > Not solid evidence.
The structured programming revolution of the '70s has cleaned up to the point that few people have seen goto-based code. For proof by personal revelation, check http://ftp.stratus.com/vos/multics/pg/moo.pl1 It's actually a good program for its day, pre Boehm and Jacopini. Trying to make a change, finding a certain place to put new code, is surprisingly hard -- not impossible, of course. Donald Knuth's vindication of some goto statements is at http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf Mel.
"CBFalconer" <cbfalconer@yahoo.com> wrote in message 
news:4815392F.5A73CD1E@yahoo.com...
> Steve at fivetrees wrote: >> "Chris H" <chris@phaedsys.org> wrote: >> > ... snip ... >> >>> However as with all things there are a few exceptions where got >>> is the cleanest solution. In those cases you need to deviate and >>> be able to stand up in court in 3 years time with your deviation. >> >> Sorry, but I disagree. There are always - ALWAYS - logically- >> equivalent structured alternatives to goto, which will not bite >> your ass anywhere near as badly. > > Those equivalents are not free. General implementation requires > the addition of flag variables. This was proven about 50 years > ago.
Absolutely. And it's a small price to pay. Given a choice between goto and a flag (or state) variable or two, guess which one I'd choose ;). Not because of religion, but because of clarity. Steve
On 26 Apr, 07:57, Chris H <ch...@phaedsys.org> wrote:

> Intestinally the "goto" is bad" came from a paper by Dykstra (not Wilco > :-) and AFAIK no one has really challenged it but just taken it as read.
See Donald Knuth (1974). "Structured Programming with Goto Statements". Computing Surveys 6 (4): 261=96301. (e.g., http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf) Also available in "Literate Programming" (ISBN 0-937073-80-6). stephen
In message 
<f0c87e4b-e426-4043-bce7-2de20250092d@b1g2000hsg.googlegroups.com>, 
stephen <stephenbennyhat@gmail.com> writes
>On 26 Apr, 07:57, Chris H <ch...@phaedsys.org> wrote: > >> Intestinally the "goto" is bad" came from a paper by Dykstra (not Wilco >> :-) and AFAIK no one has really challenged it but just taken it as read. > >See Donald Knuth (1974). "Structured Programming with Goto >Statements". Computing Surveys 6 (4): 261&ndash;301. >(e.g., http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf) >Also available in "Literate Programming" (ISBN 0-937073-80-6).
Many thanks. I will raise this at the next MISRA-C meeting. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Folks,

I always face the "goto would be nice and neat here" problem in all my 
library initialization routines.

It's somewhat identical to the "file open" thing CBFalconer postet 
elsewhere, except that I don't just open 4 files. I initialize several 
sub-systems and all sub-system build up onto each other. So subsystem N 
must never be initialized unless subystem N-1 succeded.


I think we've all have written this kind of code.



My what I *would* like to write for such a  "master library-init 
functions" would be:

int init_the_big_library_lebowsky (foo *bar)
{
   if (!init (sub_system1(bar)) goto failed1;
   if (!init (sub_system2(bar)) goto failed2;
   if (!init (sub_system3(bar)) goto failed3;
   if (!init (sub_system4(bar)) goto failed4;
   if (!init (sub_system5(bar)) goto failed5;
   if (!init (sub_system6(bar)) goto failee6;
   if (!init (sub_system7(bar)) goto failed7;
   if (!init (sub_system8(bar)) goto failed8;

   // we did it!
   return (E_SUCCESS_CODE);

   failed8: { de_init_subsys7(); return ("E_FUCKUP7\n"); }
   failed7: { de_init_subsys6(); return ("E_FUCKUP6\n"); }
   failed6: { de_init_subsys5(); return ("E_FUCKUP5\n"); }
   failed5: { de_init_subsys4(); return ("E_FUCKUP4\n"); }
   failed4: { de_init_subsys3(); return ("E_FUCKUP3\n"); }
   failed3: { de_init_subsys2(); return ("E_FUCKUP2\n"); }
   failed2: { de_init_subsys1(); return ("E_FUCKUP1\n"); }
   failed1: { return ("E_FUCKUP&#4294967295;\n"); }
}


Yes, you counted right: 8 gotos. But the program flow is as easy as it 
could be.

Compare this to a 8 level deep nested tree with " '{'-char must match 
the same line"-rule obeyed, and the "must not put more than 4 levels of 
nesting within a function-rule obeyed as well.

My innocent "initialize the big-library"-function has to be splitted 
into at least two functions and will be expanded to roughly 100 lines of 
dada-code.

The orignal - also it uses goto - is much easier to understand.

Will the MISRA-conformant function become more understandable? I don't 
think so.

For init-orgies like this goto's are a god-sent.

Nils

Nils wrote:

> Folks, > > I always face the "goto would be nice and neat here" problem in all my > library initialization routines. > > It's somewhat identical to the "file open" thing CBFalconer postet > elsewhere, except that I don't just open 4 files. I initialize several > sub-systems and all sub-system build up onto each other. So subsystem N > must never be initialized unless subystem N-1 succeded. > > I think we've all have written this kind of code. > > My what I *would* like to write for such a "master library-init > functions" would be: > > int init_the_big_library_lebowsky (foo *bar) > { > if (!init (sub_system1(bar)) goto failed1; > if (!init (sub_system2(bar)) goto failed2; > if (!init (sub_system3(bar)) goto failed3; > if (!init (sub_system4(bar)) goto failed4; > if (!init (sub_system5(bar)) goto failed5; > if (!init (sub_system6(bar)) goto failee6; > if (!init (sub_system7(bar)) goto failed7; > if (!init (sub_system8(bar)) goto failed8; > > // we did it! > return (E_SUCCESS_CODE); > > failed8: { de_init_subsys7(); return ("E_FUCKUP7\n"); } > failed7: { de_init_subsys6(); return ("E_FUCKUP6\n"); } > failed6: { de_init_subsys5(); return ("E_FUCKUP5\n"); } > failed5: { de_init_subsys4(); return ("E_FUCKUP4\n"); } > failed4: { de_init_subsys3(); return ("E_FUCKUP3\n"); } > failed3: { de_init_subsys2(); return ("E_FUCKUP2\n"); } > failed2: { de_init_subsys1(); return ("E_FUCKUP1\n"); } > failed1: { return ("E_FUCKUP&#4294967295;\n"); } > } > > Yes, you counted right: 8 gotos. But the program flow is as easy as it > could be. > > Compare this to a 8 level deep nested tree with " '{'-char must match > the same line"-rule obeyed, and the "must not put more than 4 levels of > nesting within a function-rule obeyed as well. > > My innocent "initialize the big-library"-function has to be splitted > into at least two functions and will be expanded to roughly 100 lines of > dada-code. > > The orignal - also it uses goto - is much easier to understand. > > Will the MISRA-conformant function become more understandable? I don't > think so. > > For init-orgies like this goto's are a god-sent. > > Nils
I probably missed something. I am not sure why this doesn't also solve the problem and gets rid of the goto's. The generated code size would be very similar. int init_the_big_library_lebowsky (foo *bar) { if (!init (sub_system1(bar)) { return ("E_FUCKUP&#4294967295;\n"); } if (!init (sub_system2(bar)) { de_init_subsys1(); return ("E_FUCKUP1\n"); } if (!init (sub_system3(bar)) { de_init_subsys2(); return ("E_FUCKUP2\n"); } if (!init (sub_system4(bar)) { de_init_subsys3(); return ("E_FUCKUP3\n"); } if (!init (sub_system5(bar)) { de_init_subsys4(); return ("E_FUCKUP4\n"); } if (!init (sub_system6(bar)) { de_init_subsys5(); return ("E_FUCKUP5\n"); } if (!init (sub_system7(bar)) { de_init_subsys6(); return ("E_FUCKUP6\n"); } if (!init (sub_system8(bar)) { de_init_subsys7(); return ("E_FUCKUP7\n"); } // we did it! return (E_SUCCESS_CODE); } w..
On 29 Apr, 21:57, Nils <n.pipenbri...@cubic.org> wrote:

> int init_the_big_library_lebowsky (foo *bar) > { > if (!init (sub_system1(bar)) goto failed1; > if (!init (sub_system2(bar)) goto failed2; > if (!init (sub_system3(bar)) goto failed3; > if (!init (sub_system4(bar)) goto failed4; > if (!init (sub_system5(bar)) goto failed5; > if (!init (sub_system6(bar)) goto failee6; > if (!init (sub_system7(bar)) goto failed7; > if (!init (sub_system8(bar)) goto failed8; > > // we did it! > return (E_SUCCESS_CODE); > > failed8: { de_init_subsys7(); return ("E_FUCKUP7\n"); } > failed7: { de_init_subsys6(); return ("E_FUCKUP6\n"); } > failed6: { de_init_subsys5(); return ("E_FUCKUP5\n"); } > failed5: { de_init_subsys4(); return ("E_FUCKUP4\n"); } > failed4: { de_init_subsys3(); return ("E_FUCKUP3\n"); } > failed3: { de_init_subsys2(); return ("E_FUCKUP2\n"); } > failed2: { de_init_subsys1(); return ("E_FUCKUP1\n"); } > failed1: { return ("E_FUCKUP=DF\n"); }
Isn't the point that you "de-init" everything you init, so the returns after the failed cases are wrong? It seems to me that you could benefit from some structure here: int init_the_big_library_lebowsky (foo *bar) { static const struct { int (*init)(foo*); void (*de_init)(void); } sys[] =3D { {init_sub_system0, de_init_subsys0,}, {init_sub_system1, de_init_subsys1,}, /* ... */ }; int i; for (i =3D 0; i < NELEMS(sys); i++) { if (! (*sys[i].init)(bar)) { // walk back "de-initialising" everything. while (--i >=3D 0) { (*sys[i].de_init)(); } return E_ERR; } } return E_OK; } I wouldn't quite adopt that style in production code, but I stand by the idea. The code only needs to be made right once and adding a new "sub system" is trivial. (I neither tested it, nor proved it correct.) stephen