14

I have a program in which i need to break out of a large bunch of nested for loops. So far, the way most people have been telling me to do it is to use an ugly goto in my code.

Now, if i create a bunch of local stack (i think that's what they are called, if not, i mean just regular variables without using the new command) variables inside my loops and my program hits that one if statement that triggers the goto, will i encounter a memory leak due to my program exiting many loops improperly and not cleaning up the local variables?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Faken
  • 11,352
  • 17
  • 59
  • 74
  • You will not leak memory with those autos (what you called stack). But please DO NOT USE GOTO. – R. Martinho Fernandes Aug 11 '09 at 02:28
  • 8
    What's wrong with GOTO? – Billy ONeal Aug 11 '09 at 02:30
  • Related question: http://stackoverflow.com/questions/1257744 – Greg Hewgill Aug 11 '09 at 02:31
  • @Martinho Fernandes: I sense you discourage the use of GOTO statements :) Have a story to share? – marcc Aug 11 '09 at 02:32
  • 12
    Yeah. Forward-only goto jumps are not evil. I like them much better than check variables at every loop. They are also very good for error handling function exits in C. – Zan Lynx Aug 11 '09 at 02:42
  • @zan Lynx: actually that was the entire reason i am using gotos. The purpose was to detect a divide by zero and the return to the user that something was wrong with the data set. If the data set was correct, you wouldn't encounter this problem, if not, the data is wrong and the program should stop processing and move onto something else. – Faken Aug 11 '09 at 02:46
  • 2
    If you are reacting to something like a divide by zero, then you might want to consider throwing an exception instead. – D.Shawley Aug 11 '09 at 02:50
  • 4
    Maybe I was a little harsh in the comments. I admit there may be a few niches were `goto` is not (much) harmful. But then I like to quote the first comment in this answer: http://stackoverflow.com/questions/1024361/is-using-goto-a-legitimate-way-to-break-out-of-two-loops/1024395#1024395. "+1: if it's complex enough to consider a goto, it's complex enough to encapsulate in a function and avoid the goto." – R. Martinho Fernandes Aug 11 '09 at 02:50
  • @D.Shawley: yea...i don't know what those are...lol – Faken Aug 11 '09 at 03:11
  • 1
    @Martinho: Firstly be careful with blanket statements because: "Blanket statements are always wrong" ;) In the answer to question 1024361, the resulting program structure is just as complex as if goto had been used, the code uses 'return' rather than 'goto' but the effect is the same. One difference is that the loop is now separated from the caller, which potentially makes it harder to understand what the function is actually doing. – Richard Corden Aug 11 '09 at 08:39
  • 2
    Think of `return` as of a structured `goto`. If a `return` would leak, then so would a `goto`. (And ones you're at it, consider using the structured approach instead of the spaghetti one, put that code into its own function and break out using a `return`. The rule of thumb Martinho quotes is great.) – sbi Aug 11 '09 at 08:43
  • 1
    @sbi: One way of reading your comment is that you're implying: "goto can be used to create spaghetti code therefore all code that uses goto is spaghetti code". Is that really what you want to say? The two main arguments to blanket ban goto are the above (which is pretty poor TBH), and the fact that goto affects program structure. However the structured programming argument also apply to things like 'break', 'continue' and 'return'. Why single out 'goto'? Of course 'goto' can be misused but so can nearly every feature of evey language! – Richard Corden Aug 11 '09 at 09:35
  • 2
    @Richard: If I see `break`, `return` and other "structured gotos", I see at first glance where they jump to. They are thus a lot easier to understand than `goto`. – sbi Aug 12 '09 at 10:07

10 Answers10

21

No, you will not cause a memory leak. Using a goto is not "exiting loops improperly." It's just not generally recommended from a code-structure point-of-view.

That aside, when you leave the loop, the local variables will go out of scope and be popped off of the stack (i.e. cleaned up) in the process.

Robert Cartaino
  • 27,494
  • 6
  • 45
  • 67
  • To exit a loop early you can: (a) use a goto with a label. (b) use an extra loop condition object, declared before the loops and checked in the conditional-statement of each loop. (c) similar to 'b' but check the status of the condition object "break" if required. Finally (d) you split the function in two and use a return to jump out of the loop. IMHO, only one of these clearly highlights the intent of the author of the code. An additional benefit is that goto makes it trivial to search for these rare situations and so they can be peer reviewed easily. – Richard Corden Aug 11 '09 at 08:52
6

Stack variables (autos, not autobots) aren't "leaky" like variables allocated via new() or malloc().

As far as the "uglyness" of gotos that's just dogmatic. Read Knuth, he was just as brilliant as Dijkstra. http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf Avoid pasta based programming, but careful use won't degrade into spaghetti.

Dijkstra didn't like them BECAUSE most of what you can do with gotos can be done with other structured programming techniques and uses less code therefore making the other structured less error prone.

Understand that gotos shouldn't be your first solution, and don't go out of your way to use them, but if it makes sense don't submit to dogmatic lench mobs. The break statement is a just a goto in disguise designed for cases where strict adhearance to the "Thou shalt not use gotos" commandment didn't make sense.

NoMoreZealots
  • 5,274
  • 7
  • 39
  • 56
  • 1
    Dijkstra didn't like them because everyone's habitual use of them was proving barrier to adoption of structured programming. break is not "goto in disguise" any more then else or while are "goto in disguise". They are all structured programming constructs which result in non-sequential transfer of control. – Steve Jessop Aug 11 '09 at 12:13
  • 4
    Break breaks the "single exit" critera which Dijkstra was so fond of. It drops you out of the middle of a well structured construct such as a loop, which has a single entry and single exit. A break has to be used in conjuntion with a conditional evaluation to be practical. if goto was the type of statement dijstra wanted replace by structured programming. if break is the identical construct where the only difference is goto was replaced by break. Break is consider only marginly better than a goto for these cases because you are limited in where the break can goto. – NoMoreZealots Aug 11 '09 at 13:36
  • Break is considerably "better" than goto, for precisely the reason that there is only one place where the break can go. Such limitations are exactly what distinguishes structured programming as an innovation. "goto in disguise" is no more than a McCarthyite slur - anyone can find some similarity between absolutely any flow control and "goto". But that's hardly relevant to whether the technique in question provides structure to aid in code comprehension. Loop termination with break does exactly that. – Steve Jessop Aug 12 '09 at 22:51
  • When you increase the use of goto's statement, you increase in the complexity of the program. You can no long simply look at the loop condition to determine what state of the variable is when you exit the loop. This was specifically one Dijkstra's objections, that's not my opinion it's in his paper, and it also applies to the break statement. Dijkstra was very academic, practically if over use either it has negative effect on your ability analysis the behaviour of your program, but CAREFUL application in only absolutely required cases can be useful. And that applies to both goto and breaks – NoMoreZealots Aug 13 '09 at 12:07
  • Your reading of "Go To Statement Considered Harmful" perhaps is different from mine. I don't think break is an "unbridled use of go to" making it "terribly hard to find a meaningful set of coordinates in which to describe the process progress", because break is inherently bridled to its loop. I "carefully" apply it whenever there are multiple criteria to end the loop, which are naturally calculated at different points. It's not absolutely required, you could do redundant work in order to collect all tests in a single "while" or "for" condition. But IMO that's almost always less clear. – Steve Jessop Aug 13 '09 at 14:06
  • On the inside of a looping structure determining the state of the software upon exit analytically becomes an intractable directly proportional to the number of either breaks or gotos when used in nested logic. However breaks are somewhat safer due to the fact that it is "bridled" to the loop. Dijkstra avocated co-generating a mathmatic proof with every program written, this is at the heart of his philosophy. The analytical complexity of a break would not fit his ideals of mathmatical elegance. Again I state Dijkstra was very academic, favoring correctness over productivity & efficiency. – NoMoreZealots Aug 13 '09 at 15:07
  • Sure, and in general it's proportional to the number of branches (well, or the exponent of the number). It makes no difference to the analysis whether the branches are generated by "goto", "break", "while" or "if", other than that of these "break" and "if" generate only forward branches. If you or Dijkstra is claiming that `while(condition && blah) { something(); if (blah) otherthing(); }` is easier to analyse formally than `while(condition) { something(); if (!blah) break; otherthing(); }`, then you're making it up. – Steve Jessop Aug 13 '09 at 16:17
  • All it achieves formally is to ensure that the post-condition of the loop is completely expressed in the while() condition, and does not require consideration of the conditions at each break. But the two are structurally equivalent (once you've done the extra work in the no-break case to figure out with data flow that blah==false does result in exit). It's just a case of taking the boolean OR of the two program states which exit the loop instead of the boolean OR of the two conditions which can fail at "while". So it's down to which is easier - data flow or control flow analysis. – Steve Jessop Aug 13 '09 at 16:34
  • The provided pdf is no longer available. – Connor Clark Oct 19 '22 at 04:48
2

No. You can only leak memory that is dynamically allocated.

hobodave
  • 28,925
  • 4
  • 72
  • 77
  • 1
    You can leak memory in other ways. Allocate a few dozen megabytes on a thread stack, then go to sleep for a while, for example :) – bdonlan Aug 11 '09 at 03:08
  • +1, hobodave. You, sir, are the first to make me crack up today. – jkeys Aug 11 '09 at 05:58
  • 2
    Faken didn't ask whether the stack variable itself would be leaked, he asked whether there would be any leaks as a consequence of the stack variable not being cleaned up. Had he used longjmp instead of goto, and had one of his variables been a vector, then there would be a leak (of the dynamically-allocated memory hidden behind the local object). In that case the answer could be given "Yes. You can only leak memory that is dynamically allocated". So I think some explanation of the Yes/No would be helpful ;-) – Steve Jessop Aug 11 '09 at 12:03
2

Stack variables are defined (and allocated) the moment you enter the function, and are implicitly eliminated the moment you leave the function (since the entire call stack record is popped away). No amount of bouncing around inside the function can possibly cause any havoc with memory that's been allocated the whole time. Regardless of what execution path you take through the code, the stack record will pop when control returns to the calling function, and the memory will be freed.

VoteyDisciple
  • 37,319
  • 5
  • 97
  • 97
  • Yes, but what happens if I'm not using a function? Is this also true if I use goto to break out of many loops at once inside my main program? – Faken Aug 11 '09 at 02:32
  • Everything is inside a function, even if that function is main(). The stack record for main() is allocated when the program starts, and dropped when the program ends -- the same rules as for any other function. – VoteyDisciple Aug 11 '09 at 02:36
  • In C++ and C your code is always running within one function or another. That function may be main() of course. – Bill Forster Aug 11 '09 at 02:37
  • 4
    That's not true: variables are popped on and off the stack throughout a 'scope'. Take a look at this snippet: http://codepad.org/oNcMPftp – xtofl Aug 11 '09 at 04:57
1

Goto is not always bad, but in your case you probably shouldn't be using goto.

See examples of good use of goto here and here.

If you goto a label that is outside of scope your object on the stack will be freed.

Example:

#include <iostream>
using namespace std;

class A
{
public:
  ~A() 
  {
     cout<<"A destructor"<<endl;
  }
};



int main(int argc, char**argv)
{
  {
    A a;
    cout<<"Inside scope"<<endl;
    goto l;
    cout<<"After l goto"<<endl;
  }

  cout<<"Outside of scope before l label"<<endl;

l:
  cout<<"After l label"<<endl;
  return 0;
}

This will print:

Inside scope
A destructor
After l label

Community
  • 1
  • 1
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
1

The other answers are true.... however, if you have to nest loops that differently, I'd question the design that put them there. Splitting up that logic into separate functions would be a better way to solve such a problem.

Billy3

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • Yea, i question my logic in using a 5D array too, but what works, works. I don't know, the entire program starts off as a giant loop to begin with and it just keeps looping doing a whole whack of stuff on a set of data. – Faken Aug 11 '09 at 02:41
  • Holy... a **5D** array? The only justification I've ever had for that is in PHP where arrays and object may as well be the same thing for data storage purposes... Seriously, what do you need a 5D array in C for? – Matthew Scharley Aug 11 '09 at 02:49
  • Therefore as a stranger give it welcome. There are more things in heaven and earth, Horatio, Than are dreamt of in your philosophy. – Steve Jessop Aug 11 '09 at 12:17
  • @Mmatthew Scharley: I'm processing something akin to a bitmap picture (but insted of 3 colours per pixel, its different attributes, its part of a more scientific project). The file itself is really only a 3D array, but when I need to process square chunks at a time, so in the end, it ends up more like a 5D array. 2 dimensions for the coarse x-y grid, then another 2D for the finer x-y positions of each point in the coarse grid, then a final dimension for the attribute data at each point...its messy to say the least. The worst part of it was figuring out the looping strucutre...that was hell... – Faken Aug 11 '09 at 20:53
0

No you will not.

However, make sure that any external resources are properly released. For example, if you opened a file it would be possible to jump past where it would normally be closed.

Karl Voigtland
  • 7,637
  • 34
  • 29
0

Nope. Local variables do not need to be individually cleaned up. When the stack pops, all the local variables will go away right along with it.

Mike Daniels
  • 8,582
  • 2
  • 31
  • 44
0

No, any automatic variables in your loops will not cause programming leaks if you break out of your loops with a goto statement.

Sean A.O. Harney
  • 23,901
  • 4
  • 30
  • 30
0

Will backward goto leak resources ? Or any other potential problems with below code ?

Reexecute:

        try
        {
            //Setup request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

            ....

            //Get Response
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

           if(response != HttpStatus.OK && noOfRetries < 3)
            {
                noOfRetries++;
                Thread.Sleep(10 * 1000);


                response.Close();
                goto Reexecute;
            }
            ...

            response.Close();
         }
         catch
         {

         }
Munish Goyal
  • 1,379
  • 4
  • 27
  • 49