Archived

This topic is now archived and is closed to further replies.

Breaking from all loops?

This topic is 5008 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, Ive got a deeply nested loop, deep inside my loop, i have something critical, so if this is excecuted, i want all the loops to break, like a quit, do you guys have any quick way of doing this?

Share this post


Link to post
Share on other sites
Using goto isn''t a good idea to exit loops. The reason is because loops use stack space, and when you use GOTO to exit the loop, the stack space isn''t freed. This will eventually lead to you using up all of your stack space.

I''ve had this problem myself. I haven''t yet figured out a simple way to exit the loops freely. I always have to set a variable to true, and the BREAK upon that variable being true within all the loops.

This is why goto isn''t recommended. It''s a powerful command that has to be used properly to gain it''s awesome advantages.

Share this post


Link to post
Share on other sites
I''m not sure if this is correct use of c++, but if your outer loop resides within its own function, just return from that function.

Share this post


Link to post
Share on other sites
Umm... I always thought that variables local to a function were all allocated from the stack at the start of a function. EG:

void moo(int cow)
{ //inner_a, a, b, and the local copy of cow all get allocated here

if (cow)
{
int a = 4; //or here?

if (cow > 6)
{
int a = 6; //local override of a

int b = 3; //or here?

}
}
}

If that''s right (and I''d like to know if it isn''t) then you can''t cause stack leaks using goto, since goto only works within functions. Have you actually had stack overflows caused provably by this?

Share this post


Link to post
Share on other sites
You make a good point.
Since goto only works within functions, using it should be fine. I still have some BASIC blood running through my brain, and had problems back in the day doing that with basic, but basic lets you jump out of functions, and c dosen''t. So please excuse my assumption. :D

Share this post


Link to post
Share on other sites
It depends on the loop, but you could set a boolean that tells the outer loops to break. You could also use exceptions, to do a throw and catch when you want to break.

Ultimately though it is usualy better to re-structure your loops so that you dont need to do this (if you can). Or use ''return'', like xCube suggested..

Share this post


Link to post
Share on other sites
java allows "labeled breaks". or should it be called labeled loops... anyway it works like this :


outer:
for (int i = 0; i < 10; i++) {
for (int j= 0; j< 10; j++) {
if (...) {
break outer;
}
}
}

Share this post


Link to post
Share on other sites

stayin = true;
for (i = 0; (i < 10) && stayin; ++i)
for (j = 0; (j < 10) && stayin; ++j)
for (k = 0; (k < 10) && stayin; ++k)
{
if (ImNotHappyHere)
{
DoSomething();
stayin = false;
}
}


or just set all i,j,k to 11

lonesock

Piranha are people too.

[edited by - lonesock on March 30, 2004 3:57:21 AM]

Share this post


Link to post
Share on other sites
you should redesign as much as possible.

deeply nested loops will cause masive pipeline halting
especially if the cpu cant predict the outcomes of the tests
eg. when logic data is erratic.

but yes, if you must.. go with lonesock with a slight optimization..

the inner most loop dosnt need to check "stayin", since you are
in a valid scope to call "break" and get the expected behaviour


stayin = true;

for (i = 0; (i < 10) && stayin; i++)
for (j = 0; (j < 10) && stayin; j++)
for (k = 0; k < 10; k++)
{
if (ImNotHappyHere)
{
DoSomething();
stayin = false;
break;
}
}

Share this post


Link to post
Share on other sites
It depends on what you want to do. In many cases the loops can be put inside it''s own function, and then a simple return statement can break out of the loops(and the function).

Well, I know that some purists says that a function should always have a single entry point, and a single exit point, so breaking out in the middle doesn''t follow that. But my opinion is that especially in a case like this, it generates so much cleaner code, than the alternatives, that it''s very much prefered.

Share this post


Link to post
Share on other sites
fredizzimo and lonestock are not wrong. However, I have found that goto''s as labelled breaks are acceptable because labelled breaks are a missing feature of C++.

I strongy urge against throwing exceptions to get similar behaviour. In fact, I will go so far as to say that it is simply wrong.

NB: unless you cound call/cc as an exception. C++ doesn''t even have call/cc so it should be irrelevant.

Share this post


Link to post
Share on other sites
"loops use stack space"

no, just when you call a function or return

__asm call foo ; uses stack space
__asm jmp foo ; doesnt use stack space

loops are just uses of labels and asm jump instructions

__asm {

foo:

jmp foo
}

"...your outer loop resides within its own function, just return from that function."

yes, it is correct c++

Share this post


Link to post
Share on other sites
You can throw an exception, and catch it on the outer level. That''s what exceptions are for, to abort the current flow without using a boolean, break and if (!failed){} everywhere.

Another possibility is to put the loops in a function and use return()

Share this post


Link to post
Share on other sites
quote:
Original post by Fidelio66
You can throw an exception, and catch it on the outer level. That''s what exceptions are for, to abort the current flow without using a boolean, break and if (!failed){} everywhere.



That''s not what exceptions are for. Exceptions are for exceptional cases that happens rarely(errors), not for performing logic.

Share this post


Link to post
Share on other sites
An exception is an alternative code path from the current flow (usually within if/for/while blocks) hence the name.
They are usually used for errors, but that doesn''t mean that their use is restricted to that.
You should catch them though, letting exceptions escape outside your function/class is bad practice, unless you document that behaviour.

Share this post


Link to post
Share on other sites
they would not be called exceptions then, but alternatives.

exceptions are that: exceptions. they don''t happen except if something very strange happens. they are the exceptions of the common flow.

they are just for error-handling. not even there all the time.

normally, you could refactor such double/trible/whatever loops to functions calling functions, and then, it should work out bether.. but it depends on context. in general, only goto is the real simple, nice solution. but you have to be careful with it.




If that''s not the help you''re after then you''re going to have to explain the problem better than what you have. - joanusdmentia

davepermen.net

Share this post


Link to post
Share on other sites
quote:
Original post by fractoid
Umm... I always thought that variables local to a function were all allocated from the stack at the start of a function. EG:

void moo(int cow)
{ //inner_a, a, b, and the local copy of cow all get allocated here

if (cow)
{
int a = 4; //or here?

if (cow > 6)
{
int a = 6; //local override of a

int b = 3; //or here?

}
}
}

If that''s right (and I''d like to know if it isn''t) then you can''t cause stack leaks using goto, since goto only works within functions. Have you actually had stack overflows caused provably by this?


Well, at the beginning of the function, the stack pointer is copied to ebp. Then the number of bytes used by local variables is subtracted from esp, so now you have a frame on the stack, which you can use for local variables. When you exit the function, ebp is copied to esp, so the stack is in the same state as when you entered the function. So a goto won''t result in a stack memory leak, or something like that.
the initialisation of the local variables does happen at the place where you place int i = 5; in your code.
So far there are no problems with goto, but if you use classes, the ctor is called when the object is created, and the dtor is called when the object goes out of scope. Not when you enter the function, and when you leave the function. So if you only use int''s, float''s and other build in types, then you can use goto safely, but if you use classes, you have to be very carefully with goto.

btw. visual c++ .net calls the constructor even if you skip the end of the scope with a goto, so maybe it isn''t even a problem. I don''t know what the standard says about this, though.

btw. gcc calls the destructor too, so I think it''s no problem to goto anywhere, so you can just ignore my post.


My Site

Share this post


Link to post
Share on other sites
What are you guys smoking? Gotos don''t leak stack space, destructors do get called, etc.

In javascript and probably other languages you can give a name to a loop, and then write ''break loopname;'' to get out of a bunch of them. It would be a nice feature for c/c++.

Share this post


Link to post
Share on other sites

struct MyLoopException;

func foo() throw(MyLoopException)
{
try
{
for(int a = 0; a < 1000; ++a)
{
for(int b = 0; b < 1000; ++b)
{
for(int c = 0; c < 1000; ++c)
{
if((c == 545) || (some other conditional))
throw MyLoopException();
}
}
}
}
catch(MyLoopException)
{
cout << "Loop over" << endl;
}
}

Share this post


Link to post
Share on other sites
I don''t like exceptions, but...

Exception do have their use but using them that way is abusing, horribly wrong and uglifying.

goto is the perfect candidate for breaking from nested loops. Period.

Share this post


Link to post
Share on other sites