Slashdot Mirror


Empirical Study On How C Devs Use Goto In Practice Says "Not Harmful"

Edsger Dijkstra famously opined in 1968 on the danger of Goto statements. New submitter Mei Nagappan writes with a mellower view, nearly 50 years later: By qualitatively and quantitatively analyzing a statistically valid random sample from almost 2 million C files and 11K+ projects, we find that developers limit themselves to using goto appropriately in most cases, and not in an unrestricted manner like Dijkstra feared, thus suggesting that goto does not appear to be harmful in practice. (Here's the preprint linked from above abstract.)

36 of 677 comments (clear)

  1. I prefer the Comefrom statement by Anonymous Coward · · Score: 5, Funny

    It gives me so much more flexibility and power. The computed comfrom is even better.

  2. why? by Anonymous Coward · · Score: 5, Insightful

    Is that because they were warned by Djikstra that it would be harmful to use it haphazardly? Or is it for some other reason?

    1. Re:why? by ShanghaiBill · · Score: 3, Insightful

      Is that because they were warned by Djikstra that it would be harmful to use it haphazardly? Or is it for some other reason?

      1. Because if you use goto in a class assignment, you lose points.
      2. Goto is easy to avoid, and is a symptom of a poorly designed program.
      3. Some compilers don't even try to optimize a function containing a goto.

      I have occasionally used goto as a quick hack, usually to handle error conditions.
      When I later go back and refactor the code, it is always cleaner and more readable without the goto.

    2. Re:why? by firewrought · · Score: 5, Interesting

      Is that because they were warned by Djikstra that it would be harmful to use it haphazardly?

      Programmers are more used to structuring their code (using functions, modules, etc.) and using best practices (minimizing globals, separation of concerns, etc.). This was not so much the case in the late 60's. That, combined with the "goto stigma", means that average developers avoid goto usage and good developers know when it's worth it.

      We saw a similar backlash with the concept of operator overloading. People abused it in C++, the Java designers overreacted and prohibited it, but most languages since then recognize that "yeah, operator overloading's really nice when you're building an API for mathematical constructs" (like complex numbers, quaternions, and matrices). So it's there in C#, Python, D, Rust, Scala, but (from the little I've seen) people seldom abuse it these days.

      --
      -1, Too Many Layers Of Abstraction
    3. Re:why? by Anonymous Coward · · Score: 5, Interesting

      Really? You loose point for what is really the most sane way to handle cleanup in C? Have the instructors in those courses actually done any real work outside of academia? This is a very common pattern that I've seen in almost every large C code base that I've worked on.

      static int
      do_some_work (context_t context,
                    int x,
                    error_t **error)
      {
          int rv = 0;
          database_t *db;
          data_t v;

          db = get_db (context, error);

          do some work ...

          v = compute_v (context, db, error);
          if (!v)
              goto out;

          more work ...

      out:
          return rv;
      }

      It makes it so much cleaner and easier to read.

    4. Re:why? by Bengie · · Score: 4, Informative

      There may be a better pattern, but in a few cases, I found Goto a lot easier to read than 20 layers of nested If statements. Essentially a situation where you have a pipeline of code doing one stage at a time, but you need it to immediately stop if any one of those stages did not work.

      Not to mention all conditional statements and loops are just a subset of goto. Try writing some ASM.

    5. Re:why? by Austerity+Empowers · · Score: 4, Interesting

      Computer Science and Computer Programming are two different things. The academics are always on a quest for purity, people who work for a living want to get things done as cleanly and quickly as possible. Frequently the two minds align, but you won't convince the academic your goto is pure anymore than he can convince you to rewrite the code to remove it (which you could do).

    6. Re:why? by sjames · · Score: 4, Insightful

      1 and 3 are certainly true. 2 is not always. For example, if an error condition requires unwinding such as releasing resources. Compared to deeply nested ifs and having to essentially duplicate the entire control flow in the bottom half of the function, gotos can make things much more readable and even improve performance.

      Perhaps a better statement is that goto will be found in code that is either very well designed or very poorly.

    7. Re:why? by fahrbot-bot · · Score: 4, Insightful

      There may be a better pattern, but in a few cases ...

      Like many (most?) tools, the GOTO can be used and abused. Only pendants are convinced the issue is black and white.

      --
      It must have been something you assimilated. . . .
    8. Re:why? by Anonymous Coward · · Score: 5, Insightful

      If I worked for someone as rigidly blind as yourself, I'd have left years before you "fired me", "manager in your dreams".

      THE ONLY RULE is that rules are meant to make you think carefully before you break them.

      Rules are for the guidance of the wise and obedience by fools.

      You, sir, are a fool.

    9. Re:why? by tepples · · Score: 5, Insightful

      How many levels of nested if blocks are you willing to tolerate solely in the name of avoiding a single use of the keyword goto?

    10. Re:why? by Chris+Mattern · · Score: 3, Insightful

      If operator overloading is only useful for mathematical constructions, why not simply bake those things into the language and be done with it

      Because there are an infinite number of possible mathematical constructions. You can't bake them all into the language; you need to provide facilities for the programmer to write his own.

    11. Re:why? by ClickOnThis · · Score: 3, Insightful

      I was wondering that too, but, there is another one.... what if the real issue was simply Djikstra's underestimation of how obvious the pitfalls with goto are.

      1968 was the year Djikstra wrote his article. At that time, arguably the dominant languages (FORTRAN IV and maybe BASIC) did not have structured control-flow constructs such as if-then-else, do-while and begin-end blocks. Others that contained these constructs (PL-I and Algol come to mind) were struggling for mind-share.

      Without structured control-flow constructs, one is pretty much forced to write goto statements everywhere. I think Djikstra's cautioning against the use of gotos was also a call to abandon them in favor of the structured approaches that the new languages supported. And he was right: if you're using gotos to replace structured control-flow, then you're abusing gotos.

      --
      If it weren't for deadlines, nothing would be late.
    12. Re:why? by zieroh · · Score: 4, Insightful

      An improperly structured program, will behave however the compiler felt like making it behave when it turned your lines of gibberish posing as code into machine instructions that actually manipulate registers and memory spaces.

      This misses an important point that (apparently) needs stating: complex and/or deep nesting makes code more difficult to understand by programmers (perhaps even the one that wrote the code in the first place). A simple goto-based assertion macro goes a long way toward linearizing the flow of code such that it is simple to understand. If the compiler has trouble with that, then the guy that wrote the compiler needs to try harder.

      --
      People who say "sheeple" have about as much sophistication as an AOL user, and in fact are probably actually AOL users.
    13. Re:why? by pla · · Score: 3, Interesting

      How many levels of nested if blocks are you willing to tolerate solely in the name of avoiding a single use of the keyword goto?

      If GOTO would actually alleviate that problem for you - You've already done something very, very wrong.

      I have written a lot of code in my life - Thousands of projects, millions of lines of code (for whatever that means), across a dozen languages and twice as many platforms. And outside Assembly (and DOS batch, if you want to count that as a "language"), I have not ever encountered a situation where I thought to myself "gee, I could really improve this with a GOTO, if only everyone wouldn't laugh at me for it".

      I have, however, removed some pretty heinous uses of GOTO from other people's code. The most common one I see, people can't quite bring themselves to "return" from an error handler in the middle of a function, so they instead GOTO the end of it. Really??? Talk about missing the forest for the trees!

      I don't think I would so much call GOTO "harmful", so much as "completely unnecessary in any modern language".

    14. Re:why? by beelsebob · · Score: 4, Insightful

      The problem is that the above is a remarkably simple case. The reality for a lot of cases where goto gets used for error handling is that with the above what you would end up writing is:

      bool success = doSomethingThatMightFail();
      if (success) {
              success = doSomethingElseThatMightFail();
              if (success) {
                      success = doMoreFailingStuff();
                      if (success) {
                              success = yepMoreFailingStuff();
                              if (success) { ...
                              }
                      }
              }
      }
      if (!success) {
                cleanupWork
      }

      Meanwhile with a reasonably constructed macro to wrap his pattern, you end up with:
      bool success = true;
      CHK(doSomethingThatMightFail());
      CHK(doSomethingElseThatMightfail());
      CHK(doMoreFailingStuff());
      CHK(yepMoreFailingStuff());

      end:
      if (!success) {
              cleanupWork
      }

      That's much easier to read, and just as safe.

      Don't get me wrong, in a language where you can use exceptions for this, or better yet, the error monad, you should absolutely use those more abstracted concepts, but in plain C, this really is the best approach to handling errors in code where everything you do could go wrong.

    15. Re:why? by dargaud · · Score: 4, Insightful

      yeah, GOTO the end and do some cleanup and/or error reporting, which is common to all the gotos. I don't see a problem with that. It's clear, simple and avoid heinous if/else deep nestings.

      --
      Non-Linux Penguins ?
    16. Re: why? by Darinbob · · Score: 5, Insightful

      What if I actually am an expert? Am I still bound by your superstitions about goto?
      It's one thing to tell a student or beginner to avoid goto, but another thing to place an absolute prohibition on them.

      The original goto-considered-harmful paper was written at a time when structured programming was extremely rare, spaghetti code was common, and the flowchart was a common design method. We're decades past that time though and the general programming style everywhere is to be highly structured. So the same repulsion about using goto is no longer necessary, we know enough to not use it at a whim but should be allowed to use it when it is indeed appropriate in languages which do not have the necessary structured constructs to avoid it.

    17. Re:why? by UnderCoverPenguin · · Score: 4, Interesting

      While I agree that certain constructs, like "goto" should not be used, I will point out that the full title of the 2004 version of the MISRA C document is:

      MISRA C:2004 Guidelines for the use of the C language in critical systems

      Note the word "Guidelines".

      Also note section 4.3.2, which discusses deviation procedures. In summary, it recognizes that full compliance is not always practical. And when deviations are made, they must be documented, justified and reviewed. Sometimes, such reviews involve showing 2 versions of the code in question: One without the deviation and the other with, so that the relative risks can be analyzed and discussed. Sometimes this process can result in an alternative with either a "less serious" deviation or no deviation. And sometimes the deviations are approved as-is.

      At the consulting company I work for, how strictly the various guidelines (not just MISRA, as only a few of our clients are automotive) deviations are approved depend on the customer. We certainly make great effort to only deviate from the various guidelines when the risks of compliance outweigh the risks of non-compliance. Sometimes business considerations override engineering considerations.

      --
      Don't try to out wierd me, three-eyes. I get stranger things than you, free with my breakfast cereal. --Zaphod Beeblebr
    18. Re:why? by UnderCoverPenguin · · Score: 3, Interesting

      And how would you write acquireResources?

      --
      Don't try to out wierd me, three-eyes. I get stranger things than you, free with my breakfast cereal. --Zaphod Beeblebr
    19. Re: why? by spongman · · Score: 3, Informative

      Your post implies you don't know how the C && operator works...

  3. XKCD by rhazz · · Score: 4, Funny

    Obligatory: http://xkcd.com/292/

  4. How much unsafe use has Dijkstra prevented? by suutar · · Score: 3, Insightful

    Goto is being used safely (relatively) now, but would have the programming practices that cause that to be true become so prevalent without his warning that it had potential for problems?

    1. Re:How much unsafe use has Dijkstra prevented? by Anonymous Coward · · Score: 5, Interesting

      As someone who saw the programming practices of the 1960s and early 1970s, I can assure you that Dijkstra's warning was needed.
      It caused a massive change in practices among software professionals, within a few years GOTO had almost disappeared from most new code.
      I remember seeing code from a "sales engineer" in 1975 that was so full of buggy gotos that we refused to even attempt to debug it.
      He learned.

  5. What's the term for a prophylactic prediction? by myvirtualid · · Score: 5, Insightful

    There is an implication that Dijkstra was wrong about the goto - the implication being based on how conservatively it is used.

    Perhaps it is wiser to conclude that the goto is used so conservatively because Dijkstra was right and that programmers have, in general, taken his wisdom to heart and avoided the goto except for those instances where, properly documented, it is the best tool for the job.

    (By prophylactic prediction I mean the sort of warning or planning that completely forestalls the danger predicted, through awareness, preparation, etc. Kind of like the Y2K non-event.)

    --
    I'm here EdgeKeep Inc.
  6. goto fail by Anonymous Coward · · Score: 5, Informative

    https://www.imperialviolet.org/2014/02/22/applebug.html

  7. Well, yeah by Anonymous Coward · · Score: 4, Informative

    Because we all got the warning, and thus did not write horrible goto-festooned spaghetti code and only use goto when appropriate. This means Dijkstra's letter was a success. Also, it was Niklaus Wirth who decided to use the "considered harmful" verbiage, not Dijkstra.

  8. What's Unique To Goto? by Shakrai · · Score: 3

    I'm not a "hard core" coder (defined here as someone who does nothing but development) but I've been writing C for 15+ years (it was the first language I learned and remains my favorite) and have yet to encounter a situation where the use of 'goto' is a requirement or even better than the alternative. The one circumstance where I've seen it advocated is for the main loop of a long running program but I'm not certain why goto is any better than while (1) (or similar constructs) in this scenario. Correct me if I'm wrong but the main argument against goto is that it results in haphazard code that's hard to follow. I think this is true, even in the simple case of using goto to replace while (1), never mind the more convoluted examples that invariably result when goto enters the equation.

    So, people who are smarter than me, what am I overlooking? What C coding scenario presents itself where goto is the most eloquent solution?

    --
    I want peace on earth and goodwill toward man.
    We are the United States Government! We don't do that sort of thing.
  9. Limited sample :) by davidwr · · Score: 4, Funny

    I bet the "valid random sample" didn't include any projects from the Obfuscated C Code Contest.

    --
    Knowledge is how to play a game, intelligence is how to win, wisdom is knowing what game to play.
  10. Re:GOTO is a crutch for bad programmers by adonoman · · Score: 4, Informative
    What would you propose as a better alternative to this idiom in a language that lacks exceptions:

    void func() {
    if (!AquireResource1()) goto end;
    if (!AquireResource2()) goto cleanup1;
    if (!AquireResource3()) goto cleanup2:

    DoStuffWithResources();

    Cleanup3();
    cleanup2:
    Cleanup2();
    cleanup1:
    Cleanup1();
    end:
    return;
    }

  11. Way to bury the lead by Chess_the_cat · · Score: 5, Insightful

    Headline should read "Thanks to Dijkstra's warning, GOTO in practice not harmful."

    --
    Support the First Amendment. Read at -1
  12. Re:GOTO is a crutch for bad programmers by Anonymous Coward · · Score: 4, Informative

    Fundamentally, that *is* a GOTO. It's just a less-readable idiomatic GOTO that doesn't include the "goto" keyword.

  13. Re:GOTO is a crutch for bad programmers by sjames · · Score: 3, Insightful

    So abuse loops and nesting when you have no intention of looping? And use break which is just goto lite?

    That always seems like standing on one's head to please the compiler.

  14. longjmp() by stox · · Score: 5, Funny

    is far more entertaining than a mere goto.

    --
    "To those who are overly cautious, everything is impossible. "
  15. You shoulda seen programs before Djikstra! by mileshigh · · Score: 5, Informative

    In the 60's and much of the 70's, most people wrote in high-level languages as if they were coding assembler. Goto's all over the place. Not that they had a choice -- for example, control flow in Fortran IV, the most-used high-level language of the time, featured IF, DO (a crude version of the modern FOR -- not do), GOTO, CALL, RETURN. No else, while, do/while, no modern-style for, case, etc. AND, get this: NO BLOCKS; the IF statement controlled only a *single* statement, so that meant you often *had* to say IF (...) GOTO xxx. Just like assembler. It was awful! There were other less-popular but more-evolved languages, but unstructured practices were very often carried over to those as well. GOTOs were just how most programmers thought.

    That's the backdrop for Djikstra's condemnation of GOTO. Certainly, the then-current mass use of GOTOs was a very bad thing since it completely obscured program logic. If you read the original article, he's not so much condemning GOTO as he's arguing for structured programming.

    Consider GOTO Considered Harmful as a successful wake-up call. By keeping his message black/white, i.e. GOTO is bad, he gave his message punch and made it much talked-about. People started to think in a more structured manner (though at first we thought the "structured crowd" were a bunch of weenies), and started to demand better control-flow features. Pretty soon, structured control-flow was de rigeur in any new or revised language. Fortran even got IF/END IF in Fortran 77!

    People nowadays have hardened the anti-GOTO bias into gospel. At the time, the response was more nuanced, more in line with the spirit of what Djikstra was saying. For example, in 1974 even Niklaus Wirth's new PASCAL (a principled, hard-line structured language if there ever was one) included the goto statement with the warning in the User Manual and Report that "the goto statement should be reserved for unusual or uncommon situations where the natural structure of an algorithm has to be broken." If anybody was going to out-and-out outlaw goto, Wirth would have been the guy.

  16. I agree by NickFortune · · Score: 4, Insightful

    People forget that Djiksrtra wrote his famous missive back when the dominant languages were PL/1 and Fortran and goto was the main mechanism for flow control.

    Dijkstra's point was perfectly sensible and a valid at the time. I'm just not sure that it deserves to be elevated to the status of Eleventh Commandment.

    --
    Don't let THEM immanentize the Eschaton!