You are not logged in.
I would like to know your thoughts on the 'goto' statement, is it bad practice to use it? if not, what scenario should it be used in?
Some code I have written recently loops through multiple linked lists looking for certain information, once that information is found it is then assigned to another linked list. Now in this scenario, because many for() statements are used, and we may need to go down 5-7 loops deep, functions like malloc(), inet_ntop() may be used, if these functions fail is it then acceptable to use the 'goto' statement to divert to clean up and exit failure?
Looking forward to your reply.
Like all "Don't do this, it's bad!" commandments, there are always exceptions to the rule, and "goto" is no different... The original prohibitions against goto arose from overuse of it leading to incomprehensible spaghetti code... But, there definitely are cases where using a goto is truly the best/cleanest approach...
Now in this scenario, because many for() statements are used, and we may need to go down 5-7 loops deep, functions like malloc(), inet_ntop() may be used, if these functions fail is it then acceptable to use the 'goto' statement to divert to clean up and exit failure?
And, this right here is the absolute classic example of where using a goto is a good idea... Yes, often you just can't beat a goto in such a situation, and any other method you try to come up with will just look far uglier and clutter the code more... Anyone that complains about using a goto in such a situation has obviously never tried to actually do such a thing without using one before...
However, on the other hand, if you're getting nested 7 loops deep, you may also want to reexamine your design... You may be able to break out some of that nested stuff into separate functions or something, leading to cleaner code, and make error handling and cleanup easier... However, it's possible that's just the way things need to be too, in which case, definitely go with the goto...
Yeah, I agree with Rob here. A goto is sometimes the cleanest
way to handle error paths, especially if you can replace multiple
error paths with one error path with multiple labels. Imagine
doing two mallocs. If the second one fails you have to free the
first allocation. If other things can go wrong too then goto's
can make the code a lot clearer and more robust (less chance
of forgetting to do anything in an error path, and all error
code is in one place). This seems to be your case.
Another case where a goto is the cleanest way out is in some
situations with switch statements in a loop, where break would
get you out of the switch but not out of the loop.
And sometimes, very sometimes, you have this tricky function
with a rare "retry" case, and that retry case is pretty much the
same, but jumped from a different position within the function.
A goto is fine too then.
But a goto won't fix too deeply nested function problems, those
require just helper functions and things like that.
The hate against goto came from the time when they could jump
around anywhere in the code, in C they're limited to one function,
so they aren't as evil as they used to be.
in C they're limited to one function
We still have access to the full-on evil of global gotos, however: setjmp()/longjmp()... ;-) And, yes, even THAT bit of ugly klugery still has its (very) occassional legitimate uses...
Basically, goto is fine in error handling, however, if you still want to avoid them, check CSteps library:
It is a set of macros that hides details of initialization failure handling and rollbacks and allows to write straightforward code like:
Macros track steps succeeded and performs proper rollback without touching uninitialized parts.
Also it catches forgotten cleanups and improper order.
Moreover it allows to simulate failure of each step and verify rollback correctness.
There are a lot of macros', but code is excellently readable and error-proof
CSteps is free and open source.