views:

486

answers:

9

Hello everyone,

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?

Thanks,

-Faken

A: 

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
A: 

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
+2  A: 

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

hobodave
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
lol then you should be shot
hobodave
+1, hobodave. You, sir, are the first to make me crack up today.
Hooked
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
+2  A: 

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
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
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
In C++ and C your code is always running within one function or another. That function may be main() of course.
Bill Forster
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
+1  A: 

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

Brian R. Bondy
You are right, of course, but the timeliness of the destruction call is not shown by this output. Maybe add cout's around the 'l' label?
xtofl
@xtofl: Good idea, I Added some more couts to clarify
Brian R. Bondy
+13  A: 

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
Ahh there we go, thank you.
Faken
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
A: 

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
+1  A: 

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
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
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
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
@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
+5  A: 

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
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
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 <condition> goto was the type of statement dijstra wanted replace by structured programming. if <condition> 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
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
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
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
NoMoreZealots
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 if (blah) otherthing(); }` is easier to analyse formally than `while(condition) { something(); if (!blah) break; otherthing(); }`, then you're making it up.
Steve Jessop
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