Live data from Hacker News

Error handling style in C

pixelstech.net

41–45 of 45 posts

Re: Error handling style in C

#41
post #37

Here's the error handling I teach for C: http://c.learncodethehardway.org/book/learn-c-the-hard-waych... It's using the gotos, but I make macros that hide the actual word "goto" away so that idiots (who think goto is bad because of a ranting "paper" written decades past) will not notice it. That and I print out error diagnostics, the location of the error at the time, and the errno. These macros probably saved me a g…

>That and I print out error diagnostics, the location of the error at the time, and the errno. These macros probably saved me a good decade of time finding errors in C.

Line number and file macros are freaking awesome. Out of everything on that page those should be the major takeaway for the reader.

I also think it would be a good idea to add some context to why the goto is so useful in those examples. If any of the checks fail, you're in a full-stop, stick-a-fork-in-us-we're-done error state. Since you know that the function's operations have failed, and that you should be cleaning up everything immediately, goto is the right choice.

Re: Error handling style in C

#42
post #9

A forward jumping goto (to a single target inside a function) is just perfect for C error handling code. Don't be misguided by a silly principle of goto's being always bad. They get the job done in the cleanest possible way, so you should use them for doing cleanups. The examples did not have any resources to clean up, and that is what makes error handling in C painful. In the absence of any cleanup routines, this wi…

Why should the goto be to one single target? Multiple goto statements are good for multiple clean ups without adding indentation levels and without having artificially long logic ands. For example: int init_abc() { if (!init_a()) goto err_a; if (!init_b()) goto err_b; if (!init_c()) goto err_c; return 1; err_c: cleanup_b(); err_b: cleanup_a(); err_a: return 0; } seems to be the cleanest way to do what it does in C. F…

I'm actually curious how the compilers would handle this. The compiler may inline the gotos so it's really:

  int init_abc()
  {
      if(!init_a())
          return 0;
      if(!init_b())
          cleanup_a();
          return 0;
      if(!init_c())
          cleanup_a();
          cleanup_b();
          return 0;
      return 1;
  }

Re: Error handling style in C

#43

the goto style. you can escape goto by the following trick: do { if (!do_something( bar )) { break; } if (!init_stuff( bar )) { break; } if (!prepare_stuff( bar )) { break; } return do_the_thing( bar ); }while(0); return 0;

Congratulations, you managed to write goto-style error handling without actually using the word "goto". What exactly do you think you accomplished besides pooping up your code with a bunch of unnecessary syntax and misleading the reader into thinking there's a loop coming?

If you want to lie to yourself about not using goto, I suggest you just cut that crap out and go:

#define jumpto goto

Re: Error handling style in C

#44
post #37

Here's the error handling I teach for C: http://c.learncodethehardway.org/book/learn-c-the-hard-waych... It's using the gotos, but I make macros that hide the actual word "goto" away so that idiots (who think goto is bad because of a ranting "paper" written decades past) will not notice it. That and I print out error diagnostics, the location of the error at the time, and the errno. These macros probably saved me a g…

gcc/g++ has had __FUNCTION__ and __PRETTY_FUNCTION__ since forever (the first is just the function name; the 2nd in c++ has the argument types, class name and more) - might be a useful addition to your toolkit. It's easy to trace back from line numbers to file/function etc, but I find that the function name is actually more informative for me -- and is easily incorporated into macros such as yours at no extra cost.

C++11 and the latest C have standard equivalents for these, but I'm too lazy to look them up right now..

Re: Error handling style in C

#45
Dijkstra wrote a reasonable argument against use of a prevalent structure at the time, and titled it "a case against the goto statement". The editor of journal, Niklaus Wirth (of Pascal, Module and Oberon fame) changed the title, and the rest is history.

Historical context is VERY important: At the time - 1968, goto was often used as the main form of control. "break" and "continue" were not universally accepted as a good idea - in fact, the idea of block scopes for if/then/else wasn't universally accepted!

e.g. in the Fortran of the day, the IF statement was followed by up to 3 numbers: line numbers to go to if the IF argument was positive, zero or negative. Wanted to break out of a loop? locate a suitable number and jump to it. That was also the case for BASIC, APL, and other languages of the day. Note: line numbers, not descriptive labels (which were a luxury added to most of these languages some 20 years later). That was a big part of the problem.

The result was a lot of what became known as "spaghetti code" - even code that had no conditionals would jump back and forth to the point that identifying an unconditional thread was similar to pulling one spaghetto out of a lump of spaghetti.

Goto is not inherently bad - but at the time, its use was (in the wild) more often than not problematic. With better language semantics -- chiefly block scoping and break/continue style loop exits -- there became much fewer reasons to use goto, and it became unfashionable to use it at all.

But it still has its place:

a) breaking out of multiple scopes when the language does not natively support it. (perl, java do; c, c++ don't)

b) one way switching to a scope that doesn't naturally nest with other scopes, such as in the case of error handling. Exceptions can sometime provide a good way to do that without goto, but not always (and not every language has them)

c) efficiently threading code. The python interpreter got a boost of ~20% a few years back IIRC by the introduction of a (computed) goto alternative to the plain C "switch" decoder. One could argue that it's an optimization the compiler should do, but apparently no compiler did at the time (And I am not sure one does today).

"goto" is not inherently evil; like C macros, it solves problems that the underlying language did not get to solve in the "most proper" way. You could eliminate them for having evil uses, but you better address all the use cases, or the language expressiveness will suffer. As far as I know, no language -- including LISP -- has made it always simpler to NOT use goto.

Post reply on HN