Live data from Hacker News

Goto (2007)

beej.us

71–80 of 207 posts

Re: Goto (2007)

#71
post #49

I like the presentation of the three nexted loops. Maybe "break;" should become a shortform for a generalized "break(1);" (= break one level) if we want to avoid using goto. Perhaps this can be implemented by combining a macro with setjmmp() and longjmp() from the standard C library, without requiring a compiler change.

Yep, some goto uses were ostracized without ever providing the alternative. In other languages breaking numerous loops is done by naming the one you want to control:

  outer: for () {
    for () {
      for () {
        break outer;

Re: Goto (2007)

#72
post #44

The most amazing goto is: void main() { goto http; printf("Hello world!"); http://www.hello-world.com }

This won't actually compile, even if you format it correctly, because a label must be followed by a statement.

Re: Goto (2007)

#73
post #54

Earlier quoted context omitted.

A function that allocates resources in several steps jumps, on error, to the teardown part at the end to deallocate (in reverse order of allocation) only the resources that were allocated. The others are skipped (jumped over). It's very popular in the Linux kernel.

> only the resources that were allocated How does it know which were allocated and which were not? If you are talking about memory allocation, then you could simply deallocate all the pointers provided they were initially set to NULL. Freeing a NULL pointer is well-defined in C.

Files, sockets, mutexes are all examples of resources that aren't memory. Someone posted an example in this comment thread - [0].

[0] https://wiki.sei.cmu.edu/confluence/display/c/MEM12-C.+Consi...

Re: Goto (2007)

#74
post #4

Coming from assembly language, I always found the anti-goto sentiment rather cute. A beautiful restriction, but ultimately arbitrary. Like writing poetry. Or those novels that do not ever use the letter "e". Why would an otherwise sane person write code with "rep" and without ever using "jmp"?

I started with Asm too and probably have much the same thoughts on goto --- HLLs provide if/else and loops to simplify code, so use them when it makes sense, but when the control flow is such that the simplest solution doesn't fit within the constraints of HLL flow structures, then goto makes perfect sense.

Many of those who started with HLLs probably don't realise the machine can be far more flexible and powerful beyond their constraints. It's all about using the appropriate level of abstraction.

Re: Goto (2007)

#75
post #30

Earlier quoted context omitted.

Well, as per my previous comment it's not subjective, either. It's a "best practice" in the correct sense of the term. I.e. in most cases it is both not needed and clearer, more structured code may be written without using it. Of course, as for anything, it is useful in a very few cases, emphasis on "very few".

> improve quality by making the code better structured and easier to follow "clearer" and "structured" doesn't matter from a compiler point of view. Hence the only ones that can judge "clearer" or "structured" is us, human beings, and that's why I think it's subjective. "goto" is seen as "incorrect" only because of mere subjective reasons: "it's not clear", "it's not structured", "I read in a forum that it's bad", et…

Rust is not proven to be bug free, it's proven to be memory-safe. Rusts compiler will not save you from bugs in business logic; if you can't write lucid rust and the gunning fog of reviewing your code makes it harder to spot a bug it might not be for you.

Re: Goto (2007)

#76

Earlier quoted context omitted.

It's not arbitrary. The goal is to improve quality by making the code better structured and easier to follow. For instance, MISRA C rule 15.1 that states that goto should not be used explains: " Unconstrained use of goto can lead to programs that are unstructured and extremely difficult to understand ". Indeed, in practice that's often the case.

> For instance, MISRA C rule 15.1 that states that goto should not be used explains: "Unconstrained use of goto can lead to programs that are unstructured and extremely difficult to understand" Sure, but constrained uses are fine, right? So why blanket-ban it?

MISRA doesn't ban it, that rule is only Advisory which pretty much means you can ignore it. Rules 15.2 and 15.3 (Required) define how you can use goto if you decide to use it.

Rule 15.2 The goto statement shall jump to a label declared later in the same function (forward gotos only)

Rule 15.3 Any label referenced by a goto statement shall be declared in the same block, or in any block enclosing the goto statement (can't jump a scope level lower than current [jumping in an if block from outside] or from 2 identical but separate scopes [from one if to another independent if])

Personally, I like the Linux kernel model for goto which fits these constraints. Reading code like a shopping list and jumping to the proper cleanup point is much easier to read than having 3-4 if else levels and having to scroll the screen to make sure resources are cleaned at all levels, etc. Nothing beats making the mental model of code smaller to keep in my head and readability in my book so I'll take that approach over applying holy war-ladden absolute rules.

Note that using gotos also jives well with Rule 15.5 requiring a single exit point in functions (Advisory).

Edit: as panax wrote somewhere in this thread, CERT-C rules even recommend it

Re: Goto (2007)

#77
post #54

Earlier quoted context omitted.

> only the resources that were allocated How does it know which were allocated and which were not? If you are talking about memory allocation, then you could simply deallocate all the pointers provided they were initially set to NULL. Freeing a NULL pointer is well-defined in C.

The information is in the instruction pointer. You jump to the place that deallocates the last resource that was allocated, followed by the second-to-last etc. Also, free(NULL) is not well-defined in C, and other resource types aren't so easy to check. delete nullptr in C++ is well-defined, but you rarely need it.

> free(NULL) is not well-defined in C

Oh yes it is: https://stackoverflow.com/questions/1938735/does-freeptr-whe...

Re: Goto (2007)

#78
> Multi-level Cleanup

Used all the time a decade or so ago when writing code that made heavy use of Apple's CoreFoundation. CF could return nil (failure) for many operations, and memory management at that time was left up to the programmer.

// Not real code, approximated from recollection

bool createNestedCFThing () {

   CFDictionary *thing = nil;
   CFArray *arrayObj = nil;
   CFString *string1 = nil;
   CFString *string0 = nil;

   string0 = CFCreateString ("Hello");
   if (string0 == nil) {
      goto bail;
   }
   
   string1 = CFCreateString ("World");
   if (string1 == nil) {
      goto bail;
   }

   arrayObj = CFCreateArray ();
   if (arrayObj == nil) {
      goto bail;
   }

   if (CFArrayAddObject (arrayObj, string0) == false) {
      goto bail;
   }

   if (CFArrayAddObject (arrayObj, string1) == false) {
      goto bail;
   }

   thing = CFCreateDictionary ();
   if (thing == nil) {
      goto bail;
   }

   if (!CFDictionaryInsertObjectWithKey (thing, arrayObj, "somekey")) {
      goto bail;
   }
bail:

   if (arrayObj != nil) {
      CFRelease (arrayObj);
   }

   if (string1 != nil) {
      CFRelease (string1);
   }

   if (string0 != nil) {
      CFRelease (string0);
   }

   return thing;
}

Re: Goto (2007)

#79
post #73
post #54

Earlier quoted context omitted.

> only the resources that were allocated How does it know which were allocated and which were not? If you are talking about memory allocation, then you could simply deallocate all the pointers provided they were initially set to NULL. Freeing a NULL pointer is well-defined in C.

Files, sockets, mutexes are all examples of resources that aren't memory. Someone posted an example in this comment thread - [0]. [0] https://wiki.sei.cmu.edu/confluence/display/c/MEM12-C.+Consi...

> Files, sockets, mutexes are all examples of resources that aren't memory

I know - that's why I explicitly mentioned memory.

Re: Goto (2007)

#80
post #77

Earlier quoted context omitted.

The information is in the instruction pointer. You jump to the place that deallocates the last resource that was allocated, followed by the second-to-last etc. Also, free(NULL) is not well-defined in C, and other resource types aren't so easy to check. delete nullptr in C++ is well-defined, but you rarely need it.

> free(NULL) is not well-defined in C Oh yes it is: https://stackoverflow.com/questions/1938735/does-freeptr-whe...

I stand corrected. So, these days, null checks before free() are just for compatibility with very old systems, or more likely "tradition". I wonder where I got my wrong information? I have even seen null checks before delete in C++ code recently written by C programmers :o
Post reply on HN