3 ms·
the goto style. you can escape goto by the following trick: do { if (!do_something( bar )) { break; } if (!init_stuff( ba
by ashishb4u 14y ago
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;
- evincarofautumn 14y agoThe “goto” style is better; it avoids excessive nesting and abusing “do { … } while (…)” for something wholly unrelated to looping. You want a jump, use a jump—it’s okay. “goto” lets you unwind from any number of errors without undue nesting or repetition: int foo(int bar) { if (!do_something(bar)) goto do_something_error; if (!init_stuff(bar)) goto init_stuff_error; if (!prepare_stuff(bar)) goto prepare_stuff_error; return do_the_thing(bar); prepare_stuff_error: unprepare_stuff(bar); init_stuff_error: deinit_stuff(bar); do_something_error: undo_something(bar); return 0; }
- masklinn 14y agoYup, jumps are the best way to correctly unwrap things (e.g. if you acquired resources), and if you're using it when you need to you might as well use it everywhere so your codebase is consistent. Although I believe your jumps are in the wrong place logically speaking: if do_something() errored out, logically speaking you should not have to undo_something because do_something cleaned up its crap. So the jumps should be after the cleanups (and you should never need to unprepare_stuff). Just as the opening of a file is not in a protected scope (if opening the file fails, you don't close it)
- evincarofautumn 14y agoYou’re right, you shouldn’t need to clean up after the first failure. I was thinking, say, new_a() succeeds and new_b() fails: you don’t need to free_b() but you definitely need to free_a(). The calling function is responsible for coordinating error handling amongst those functions it calls. “…you should never need to unprepare_stuff” I was just poking fun at the useless names.
- hamburglar 14y agoCongratulations, 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