Discussion about only having one exit point in a function?

Member
Posts: 321
Joined: 2004.10
Post: #16
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.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #17
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:

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_null

In any language which has exceptions, they're probably a better solution to this!
Quote this message in a reply
Member
Posts: 321
Joined: 2004.10
Post: #18
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?
Quote this message in a reply
Member
Posts: 198
Joined: 2005.01
Post: #19
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 Smile

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...

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Quote this message in a reply
Member
Posts: 131
Joined: 2004.10
Post: #20
If you are really adamant about not using a goto you can redo his code as follows
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;
So you add two more lines but it amounts to the same.
Quote this message in a reply
Apprentice
Posts: 19
Joined: 2004.10
Post: #21
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.
Quote this message in a reply
Moderator
Posts: 771
Joined: 2003.04
Post: #22
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. Wink
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Proper Way to Exit an NSThread AnotherJake 3 6,526 Jun 6, 2006 11:14 PM
Last Post: AnotherJake
  "Command /.../jam failed with exit code 1"- huh? Joseph Duchesne 2 5,896 Mar 29, 2006 09:32 AM
Last Post: socksy