Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

In C it's generally accepted that forward jumps using goto are okay because the version that avoids goto would be complicated and confusing. Often used for error handling and memory management.


Error handling because you want to make a beeline to the handler, and memory management because you need it to be quick and goto is cheap?


In both cases, to avoid duplicating code. If you malloc() something in your function and intend on free()ing it before returning, it's often considered best practices to write the return block (which includes the free()s) once, and use "goto returnblocklabel" if you need to return early.

So rather than this:

  void test()
  {
    int *x = malloc(1000);
    int *y = malloc(1000);
    for(int i = 0; i < 999; i++) {
      if(badThing) {
        free(x);
        free(y);
        return;
      }
      doStuff()
      if(otherBadThing) {
        free(x);
        free(y);
        return;
      }
    }
    free(x);
    free(y);
    return;
  }
You'd have:

  void test()
  {
    int *x = malloc(1000);
    int *y = malloc(1000);
    for(int i = 0; i < 999; i++) {
      if(badThing)
        goto ret;
      doStuff()
      if(otherBadThing)
        goto ret;
    }
  ret:
    free(x);
    free(y);
    return;
  }


I realize your example is contrived, but a simple 'break' statement (which in essence is a goto...) would work just as well. :) I somewhat vaguely recall a situation in my C class that I wanted to use goto to avoid duplicate code but the professor had previously threatened huge negative points if his scripts detected one. (That whole semester was just as much about conforming your code to his narrow specifics because "that's what happens in the real world." as learning C.)


Can you explain what you mean by use of gotos for memory management?


Here's an example:

    void do_stuff(char *name) {
        char *my_name = strdup(name);
        if (condition_signalling_no_work()) goto done;
        if (do_something_with(my_name)) goto done;
        
        ...
        
        done:
          free(my_name);
          return;
    }
If it helps think of it as a finally block. The function does some things and no matter what it has to run that block at the end.


Ah, so for resource cleanup in general, not memory management in particular.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: