Discussion in "General help Guidance and Discussion" started by    DavesGarage    Nov 7, 2009.
Sat Nov 07 2009, 08:18 am
#1
At the behest of our website owner, I decided to open a forum thread on software programming techniques. I have been writing software for about 25 years now, and I find I am constantly learning new and innovative ways to get into trouble with my code...

I thought this could be a place where we discuss specific topics - this particular thread is dedicated to the use of GOTO, which is defined within K&R's "The C Programming Language" book as follows:

3.8 Goto and labels
C provides the infinitely-abusable goto statement, and labels to branch to. Formally, the goto statement is never necessary, and in practice it is almost always easy to write code without it. We have not used goto in this book. 
Nevertheless, there are a few situations where gotos may find a place. The most common is to abandon processing in some deeply nested structure, such as breaking out of two or more loops at once. The break statement cannot be used directly since it only exits from the innermost loop. Thus: 

       for ( ... )
           for ( ... ) {
               ...
               if (disaster)
                   goto error;
           }
       ...
   error:
       /* clean up the mess */
This organization is handy if the error-handling code is non-trivial, and if errors can occur in several places. 
A label has the same form as a variable name, and is followed by a colon. It can be attached to any statement in the same function as the goto. The scope of a label is the entire function. 
As another example, consider the problem of determining whether two arrays a and b have an element in common. One possibility is 

       for (i = 0; i < n; i++)
           for (j = 0; j < m; j++)
               if (a[i] == b[j])
                   goto found;
       /* didn't find any common element */
       ...
   found:
       /* got one: a[i] == b[j] */
       ...
Code involving a goto can always be written without one, though perhaps at the price of some repeated tests or an extra variable. For example, the array search becomes 

   found = 0;
   for (i = 0; i < n && !found; i++)
       for (j = 0; j < m && !found; j++)
           if (a[i] == b[j])
               found = 1;
   if (found)
       /* got one: a[i-1] == b[j-1] */
       ...
   else
       /* didn't find any common element */
       ...
With a few exceptions like those cited here, code that relies on goto statements is generally harder to understand and to maintain than code without gotos. Although we are not dogmatic about the matter, it does seem that goto statements should be used rarely, if at all. 



Using GOTO in your software is a widely debated issue. What are your thoughts?

Sat Nov 07 2009, 08:36 pm
#2
I believe if you know what you are doing then its not a problem using goto statement. I sometimes really feel difficult to understand why people abuse so much?

If goto can make you life simple then why not use it? I am not a master in programming but i feel wherever you can use goto just use it.

I have seen uIP 0.9 implementation by Adam Dunkels, he made a heavy use of goto statement just to make things simpler, he could also use switch case statements but he decided to use goto.

Can anyone points to problem that can arise using goto?
Sat Nov 14 2009, 09:47 am
#3
Searching the web, I ran across a very good description of when to use goto...

The author wrote:

When To Use Goto When Programming in C
Although the use of goto is almost always bad programming practice (surely you can find a better way of doing XYZ), there are times when it really isn't a bad choice. Some might even argue that, when it is useful, it's the best choice.

Most of what I have to say about goto really only applies to C. If you're using C++, there's no sound reason to use goto in place of exceptions. In C, however, you don't have the power of an exception handling mechanism, so if you want to separate out error handling from the rest of your program logic, and you want to avoid rewriting clean up code multiple times throughout your code, then goto can be a good choice.

What do I mean? You might have some code that looks like this:

int big_function()
{
    /* do some work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* do some more work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* do some more work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* do some more work */
    if([error])
    {
        /* clean up*/
        return [error];
    }
    /* clean up*/
    return [success];
}

This is fine until you realize that you need to change your cleanup code. Then you have to go through and make 4 changes. Now, you might decide that you can just encapsulate all of the cleanup into a single function; that's not a bad idea. But it does mean that you'll need to be careful with pointers -- if you plan to free a pointer in your cleanup function, there's no way to set it to then point to NULL unless you pass in a pointer to a pointer. In a lot of cases, you won't be using that pointer again anyway, so that may not be a major concern. On the other hand, if you add in a new pointer, file handle, or other thing that needs cleanup, then you'll need to change your cleanup function again; and then you'll need to change the arguments to that function.

In some cases, this might be acceptable -- but if you're making a lot of changes to your code, adding in new variables, etc. -- it may not be worth the time or the extra lines of code to make that function call.

Instead, since you know that you're going to be executing only one piece of code and then returning from the function, you might as well use a goto to jump to the very end of the function, where you have your cleanup code.

Goto is a pretty simple keyword: you just need to include a "label" placed above the target location (followed by a colon), and then direct the program to go to the label. Note that this only works within the same function; you can't just enter one function from another.

goto label;
/* Code
...
*/
label:

Now, using this, if we want to handle all our errors in one place, we'll need to add in a variable to track the return value of our function so we can return it:

int big_function()
{
    int ret_val = [success];
    /* do some work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
    /* do some more work */
    if([error])
    {
        ret_val = [error];
        goto end;
    }
end:
    /* clean up*/
    return ret_val;
}

The benefit here is that your code following end has access to everything it will need to perform cleanup, and you've managed to reduce the number of change points considerably. Another benefit is that you've gone from having multiple exit points for your function to just one; there's no chance you'll accidentally return from the function without cleaning up.

Moreover, since goto is only being used to jump to a single point, it's not as though you're creating a mass of spaghetti code jumping back and forth in an attempt to simulate function calls. Rather, goto actually helps write more structured code.

There is one thing to be aware of: while your cleanup code should be able to free all of the memory you use, there may be times when you actually want to free that memory yourself and possibly reallocate it later. In these cases, if you do call free on a ptr and then have an if([error]) between that call to free and the subsequent call to malloc, you should definitely set the pointer to point to NULL! This will prevent your jumping to the cleanup code and then calling free on that pointer a second time, which can result in a security hole (the "double free" problem).

Goto should always be used sparingly, and as a last resort -- but there is a time and a place for it. The question should be not "do you have to use it" but "is it the best choice" to use it.



The website is here: http://www.cprogramming.com/tutorial/goto.html


[ Edited Sat Nov 14 2009, 09:49 am ]
 ajay_bhargav like this.
Sat Nov 14 2009, 04:38 pm
#4
That explains a lot
I really like this method of spreading and gathering good knowledge
Mon Nov 16 2009, 08:49 pm
#5


I believe if you know what you are doing then its not a problem using goto statement. I sometimes really feel difficult to understand why people abuse so much?

If goto can make you life simple then why not use it? I am not a master in programming but i feel wherever you can use goto just use it.

I have seen uIP 0.9 implementation by Adam Dunkels, he made a heavy use of goto statement just to make things simpler, he could also use switch case statements but he decided to use goto.

Can anyone points to problem that can arise using goto?

Ajay Bhargav



The goto statement has run me into alot of problems when I started coding in embedded C. I sometimes find that using goto before closing a while(1) loop can cause 18F series PIC chips to crash. Goto can be used to make things much simpler but I personally think it is down to the programmer. While working on projects in different teams, I find that some programmers code in a style that is similar to the language they started out with.

I've noticed one guy who started out coding in assembly, his C code looks very similar in structure!
Tue Nov 17 2009, 01:09 am
#6
banked memories may cause a problem with goto i believe. 8051 is fairly simple architecture where you can jump from anywhere in range of 64K. So architectures also play big role on how you code.

but most of time Its on user how he use it or code it.
Tue Nov 17 2009, 03:22 am
#7


The goto statement has run me into alot of problems when I started coding in embedded C. I sometimes find that using goto before closing a while(1) loop can cause 18F series PIC chips to crash.

Retellect


I suspect that the compiler may be careless as to how it codes while loops.
Useful warning though.


[ Edited Tue Nov 17 2009, 03:23 am ]

Get Social

Information

Powered by e107 Forum System

Downloads

Comments

Darrellciz
Thu Apr 18 2024, 11:07 am
Charlessber
Thu Apr 18 2024, 09:29 am
BartonSem
Thu Apr 18 2024, 04:56 am
DonaldKnown
Thu Apr 18 2024, 12:24 am
utaletxcyw
Wed Apr 17 2024, 10:21 am
Anthonyvab
Wed Apr 17 2024, 08:48 am
RobertCix
Wed Apr 17 2024, 06:46 am
Astorne
Tue Apr 16 2024, 08:52 pm