Discussion about only having one exit point in a function?
Typically all my functions consist of something like the following:
This is pseudo, pseudo, and psuedo code. Did I say this was
pseudo code?
retType func(x, y, z)
{
if (x has something bad about it)
return(badX);
if (y has something bad about it)
return(badY)
if (z has something bad about it)
return(badZ)
// some super complex computation regarding x, y and z
return(superComplexComp)
}
It has one exit code except for the errors!
I have seen people who took this dictum of even error conditions
leaving the one exit point, and it really becomes unmanageable
quickly.
I've never used goto in 15 years. Just say no.
This is pseudo, pseudo, and psuedo code. Did I say this was
pseudo code?
retType func(x, y, z)
{
if (x has something bad about it)
return(badX);
if (y has something bad about it)
return(badY)
if (z has something bad about it)
return(badZ)
// some super complex computation regarding x, y and z
return(superComplexComp)
}
It has one exit code except for the errors!
I have seen people who took this dictum of even error conditions
leaving the one exit point, and it really becomes unmanageable
quickly.
I've never used goto in 15 years. Just say no.
goto is really handy in C when you have a lot of cleanup that would be duplicated throughout your code, for example, if you wrote:
Clearly that gets worse with the number of resources you allocate, and the complexity of disposing of them. Or you could write:
which could then even become:
In any language which has exceptions, they're probably a better solution to this!
Code:
void *p = malloc(i);
if (p == NULL)
{
return 0;
}
void *q = malloc(j);
if (q == NULL)
{
free(p);
return 0;
}
void *r = malloc(k);
if (r == NULL)
{
free(q);
free(p);
return 0;
}
return 1;Clearly that gets worse with the number of resources you allocate, and the complexity of disposing of them. Or you could write:
Code:
void *p = NULL, q = NULL, r = NULL;
p = malloc(i);
if (p == NULL)
{
goto failure;
}
q = malloc(j)
if (q == NULL)
{
goto failure;
}
r = malloc(k);
if (r == NULL)
{
goto failure;
}
return 1;
failure:
free(r);
free(q);
free(p);
return 0;which could then even become:
Code:
#define check_null(pointer) if ((pointer) == NULL) { goto failure; }
void *p = NULL, q = NULL, r = NULL;
p = malloc(i);
check_null(p);
q = malloc(j);
check_null(q);
r = malloc(k);
check_null(r);
return 1;
failure:
free(r);
free(q);
free(p);
return 0;
#undef check_nullIn any language which has exceptions, they're probably a better solution to this!
Damn, only OSC could give a clear and succinct example of how a
goto could elegantly be incorporated into a program. Just proves the
adage of never saying never.
Will you please, please write a programming book so all your knowledge
can be disseminated. I am serious. I've meet Phds with one tenth the
knowledge of OSC. You're not Don Knuth in disguise?
goto could elegantly be incorporated into a program. Just proves the
adage of never saying never.
Will you please, please write a programming book so all your knowledge
can be disseminated. I am serious. I've meet Phds with one tenth the
knowledge of OSC. You're not Don Knuth in disguise?
I've been doing this sort of thing for a while. It's been more or less common knowledge since Knuth wrote a paper about missing language features in C 
I stand by my previous statement though that if you need the cleanup gotos, it might be better to just break it down into sub-functions and stay cleaner...

I stand by my previous statement though that if you need the cleanup gotos, it might be better to just break it down into sub-functions and stay cleaner...
If you are really adamant about not using a goto you can redo his code as follows
So you add two more lines but it amounts to the same.
Code:
#define BBLK for(;;) {
#define ENDBBLK break; }
#define BREAK_ON(V) if (V) break
void *p = NULL, q = NULL, r = NULL;
BBLK {
p = malloc(i);
BREAK_ON(!p);
q = malloc(j)
BREAK_ON(!q);
r = malloc(k);
BREAK_ON(!r);
return 1;
} ENDBBLK;
free(r);
free(q);
free(p);
return 0;
I disagree with people who tell you should never use gotos. All of the reasons they give are perfectly valid, and (in an ideal world) you should never use a goto. But, we don't live in an ideal world, and occassionally we have to break rules to get things done. OSC's example goto is one common place where goto's are used, and another is duff's device (google it). Although both are hack-ish, they provide functionality that would be difficult/prohibitive to implement as codeblocks/if-then-else/etc. in a language that doesn't support exception handling (which C is).
Having said all that, I have never used a goto in production code (except ASM) in my life (>20yrs coding). So, my 2c is that:
(1) Keep in mind that you have this tool
(2) Avoid it all costs, but remember (1)
On an aside:
Have you ever investigated how Cocoa implements exception handling? It's an interesting question because as Obj-C is built on C it natively has no exceptions either. So how did NEXT implement exception handling???
I got curious one day, and investigated. Basically NS_DURING, etc. all use setjmp(...) and longjmp(...) -- which are the MOTHER of all gotos.
So, the engineer that invented exceptions in Cocoa used goto's exactly like I have described:
- He had a problem to solve
- There was no elegant solution that didn't involve ugliness (ie, goto's)
- He bit the bullet, and did it the way it needed to be done, and wrapped it up as clean as possible.
We should all learn from his example.
Having said all that, I have never used a goto in production code (except ASM) in my life (>20yrs coding). So, my 2c is that:
(1) Keep in mind that you have this tool
(2) Avoid it all costs, but remember (1)
On an aside:
Have you ever investigated how Cocoa implements exception handling? It's an interesting question because as Obj-C is built on C it natively has no exceptions either. So how did NEXT implement exception handling???
I got curious one day, and investigated. Basically NS_DURING, etc. all use setjmp(...) and longjmp(...) -- which are the MOTHER of all gotos.
So, the engineer that invented exceptions in Cocoa used goto's exactly like I have described:
- He had a problem to solve
- There was no elegant solution that didn't involve ugliness (ie, goto's)
- He bit the bullet, and did it the way it needed to be done, and wrapped it up as clean as possible.
We should all learn from his example.
jfaller Wrote:Having said all that, I have never used a goto in production code (except ASM) in my life (>20yrs coding). So, my 2c is that:
(1) Keep in mind that you have this tool
(2) Avoid it all costs, but remember (1)
I agree with 99% of your post, but I would add:
(3) If you remember (1), you'll eventually find some situation where you'll think: "Hey, this seems like the perfect place to use gotos", whereas if you don't, you'll find a workaround, be it refactoring, exceptions, something else. So, forget about (1) and remember your workaround instead.
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Proper Way to Exit an NSThread | AnotherJake | 3 | 5,169 |
Jun 6, 2006 11:14 PM Last Post: AnotherJake |
|
| "Command /.../jam failed with exit code 1"- huh? | Joseph Duchesne | 2 | 5,346 |
Mar 29, 2006 09:32 AM Last Post: socksy |
|

