PDA

View Full Version : goto



no-one
05-17-2006, 05:18 PM
thought:

say you had code such as this...

NOTE: using C...





object* factory(parameter1, parameter2, para....)
{
object* a = allocate memory;

if(!a)
return NULL;

a->member1 = allocate memory based on parameter1;
if(!a->member1)
{
free(a);
return NULL;
}

a->member2 = allocate memory based on parameter2;
if(!a->member2)
{
free(a);
free(a->member1);
}

/// etc................
return a;
}



error handling code is redundant... and continually grows longer....

solution 1:




void FAIL(object* obj)
{
free(obj->member2);
free(obj->member1);
// etc....
free(obj);
}

object* factory(parameter1, parameter2, para....)
{
object* a = allocate memory zeroed memory;

if(!a)
return NULL;

if(!(a->member1 = allocate memory based on parameter1))
{
FAIL(a);
return NULL;
}

if(!(a->member2 = allocate memory based on parameter2))
{
FAIL(a);
return NULL;
}


/// etc................

return a;
}



requires a specialized function... but it works and is cleaner...

solution 2:





object* factory(parameter1, parameter2, para....)
{
object* a = allocate memory zeroed memory;

if(!a)
return NULL;

if(!(a->member1 = allocate memory based on parameter1))
goto FAIL;

if(!(a->member2 = allocate memory based on parameter2))
goto FAIL;

/// etc................

return a;

FAIL:
free(a->member2);
free(a->member1);
// etc....
free(a);
return NULL;
}



cleaner requires no function... uses goto(OH NOES!!!!!)...

comments... suggestions? thoughts?

jverkoey
05-17-2006, 05:36 PM
That's a valid use of goto in my honest opinion.

Alternatively, you could do:

object* factory(parameter1, parameter2, para....)
{
int success = true;
object* a = allocate memory;

if(!a)
success = false;

if(success)
{
a->member1 = allocate memory based on parameter1;
if(!a->member1)
success = false;
}

if(success)
{
a->member2 = allocate memory based on parameter2;
if(!a->member2)
success = false;
}


if( false == success && a)
{
free(a);
a = NULL;
}
return a;
}

This allows for one to gracefully recover if necessary.

joeprogrammer
05-17-2006, 05:43 PM
What about exception handling? It may not be exactly what you are looking for, but I sure like it. The only disadvantage when you want to use exception handling is that it's much easier to write it in C++, so although C users can do it, classes allow you to take full advantage of exception handling.

If you don't know what exception handling is, go here:
http://www.flipcode.com/articles/article_exceptionhandling.shtml


Edit: this should have really been posted in the C forums :rolleyes:

no-one
05-17-2006, 06:11 PM
you disreguard many factors... firstly though the example is meant to be in C, it is quite valid in C++, and is really not even a language specific idea honestly... the example could very well be translated into many languages... the topic is not the language nor language specific solutions... exception handling is not available in C in any easy or simple means though it is the optimal solution in C++ if you disreguard the overhead associated with its use...
the idea is meant to be clean with minimal overhead and minimal complexity to the reading or function of the code(and in C)... goto overall is the simplest cleanest easiest and quite probably the fastest solution to the problem hence it is an "argument" for its use as opposed to the function version, or the flag version... or even exception handling...
in essence this is an argument for the use of goto... which is a multi-language tool.

i posted it because im curious to know if i missed something... or is this infact the best solution... and it doesnt belong in the C forum, because its about goto and programming in general... not the c language

Prelude
05-17-2006, 06:28 PM
>comments... suggestions? thoughts?
That's one of the accepted uses of goto.

psychopath
05-17-2006, 06:50 PM
I use goto's in the same way, to skip for loops in my game engines rendering code depending on the result of a frustum culling test. Very useful, IMO.

anonytmouse
05-17-2006, 07:02 PM
The nicest programming solution is to use nested if blocks. However, for a function with more than a couple of failure points the goto solution can produce far clearer code.


if((a->member1 = allocate memory based on parameter1))
{
if((a->member2 = allocate memory based on parameter2))
{
return a;
}
}

// failed

The goto solution is roughly semantically equivalent to exception handling, although exceptions can be a lot harder to debug and prove.

Prelude
05-17-2006, 07:34 PM
>The nicest programming solution is to use nested if blocks.
Except when you consider that extreme levels of indentation hinder readability. Add two more parameters, then add the code that works with the resulting memory, and you'll see the problem. You'll probably also want to add else clauses to handle deallocation of unused memory, and since you're doing that, why not more detailed error messages? It gets complicated quickly when you do it right, and adding the nested blocks suddenly isn't such a nice solution.

anonytmouse
05-17-2006, 08:45 PM
>The nicest programming solution is to use nested if blocks.
Except when you consider that extreme levels of indentation hinder readability. Add two more parameters, then add the code that works with the resulting memory, and you'll see the problem. You'll probably also want to add else clauses to handle deallocation of unused memory, and since you're doing that, why not more detailed error messages? It gets complicated quickly when you do it right, and adding the nested blocks suddenly isn't such a nice solution.

Totally agree. I'm a big fan of the goto solution. Check here (http://cboard.cprogramming.com/showthread.php?p=513544&highlight=goto) or here (http://cboard.cprogramming.com/showthread.php?p=550925&highlight=goto) or here (http://cboard.cprogramming.com/showthread.php?p=441123&highlight=goto). I'd challenge anyone to come up with a better solution for any of those three examples.