Pages: [1]   Go Down
Author Topic: Effect of 'goto' on stack?  (Read 1901 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In my code, if an error is encountered, an error function is called that holds the program in a loop until it receives one of two inputs. One continues where it left off, and the other is supposed to restart the program.

Pseudocode:
Code:
void setup()
{
//do setup stuff
}

void loop()
{
mainloop:

//loop stuff
}

void error(command)
{

while ( true )
{

if ( command = continue )
break;
else if ( command = restart )
{
setup();
goto mainloop;
}

}

}

Will using goto within a function cause problems? I'm thinking that if it compiles as a jump instruction won't it pop the stack. Unless the compiler takes care of it. All. If it is a problem, can I manually modify the return address so that on return the function jumps to the main loop?

Thanks!
Logged

Norway@Oslo
Offline Offline
Edison Member
*
Karma: 13
Posts: 2033
loveArduino(true);
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm betting you're in for a ride smiley

I thought the goto was scoped? I was actually quite sure of it.



I might as well be the one to say it: Do not use goto for this smiley-wink
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It is in fact scoped haha. I hadn't compiled in a while. Any suggestions on how to implement this? I need to exit the function and immediately return to the beginning of the loop.
Logged

Edmonton, Canada
Offline Offline
Newbie
*
Karma: 0
Posts: 47
A-R-D-U-I-N-O... GoooOOOO ARDUINO!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Goto is bad. Murderous pink teddy bear bad. It is necromancy from assembly that has wormed its way into higher level programming languages.

There is *always* a better way of doing things in C.

Ex:
Code:
#include <avr/io.h>
#include <avr/wdt.h>

enum errors {
    eContinue,
    eRestart
};

boolean triedToUseGoto = false;

void setup()
{
    // make sure we have the watchdog disabled
    // (we might have enabled it to reset with)
    wdt_disable();
    
    // set me up!
    setupFunction();
}

void loop()
{
    // main code goes here
    triedToUseGoto = true;
    
    // check for an error
    if(triedToUseGoto)
    {
        // uh-oh! an error has arisen!
        error(eRestart);
    }
}

void error(int command)
{
    switch(command)
    {
        case eContinue:
            return;
            break;
            
        case eRestart:
            // we need to reset the entire micro
            // no re-running setup code here, cuz it
            // might stay persistant.
            // so what do we do?
            // enable the watchdog timer!!!
            // (and don't pat it)
            wdt_enable(WDTO_15MS);
            while(1);
            break;
    }
}

(Haven't tested, but something along those lines should work..)
« Last Edit: June 09, 2010, 04:02:00 pm by Adrastos » Logged

Edmonton, Canada
Offline Offline
Newbie
*
Karma: 0
Posts: 47
A-R-D-U-I-N-O... GoooOOOO ARDUINO!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Though I just realized that the above code won't work with the stock bootloader, as the watchdog would keep the chip in the bootloader forever.

You could either use Adafruit's bootloader which disables the watchdog in the bootloader, or you could simply wire a pin to control the reset line of the ATMega...
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I ended up solving my problem with lots of return true/return falses...and a few goto's >.>

I know goto's aren't ideal, but theyre all to the same place (top of loop()) and I need them because there are so many nested loops :/
Logged

Holland
Offline Offline
Sr. Member
****
Karma: 0
Posts: 439
Arduino likes cookies too
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nested loops are usually the result of poor design.
Would something allong the lines of a state machine work for you?
Essentially you'd be using the main loop for your nested loops...
Should help with debugging aswell, since you know the exact order in which your program runs, and can put in debug messages accordingly.
« Last Edit: June 09, 2010, 05:09:55 pm by Imahilus » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Solved all of my problems by using 'return'. Since loop() is just a function called within main(), using return exits loop() and hits the infinite for loop that Arduino uses, restarting loop().
Logged

Australia
Offline Offline
Full Member
***
Karma: 0
Posts: 100
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
There is *always* a better way of doing things in C.

There are some specific use-cases where the judicious application of goto results in faster, more readable (and hence more maintainable) and less error-prone code.

Device-driver code that sequentially allocates resources before performing actions, where failure to allocate a resource requires the de-allocation in the reverse order is one example. Using nested "if" statements in this case pushes the main code path deep into the nesting, obfuscating the code's function.

Goto has a place in the language, but it's definitely an advanced technique that should be considered only with strong justification.
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 135
Posts: 6782
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Isn't this the sort of thing that "longjmp" and "setjmp" are used for?  I believe that they are carefully defined to do "reasonable" things with the stack.

The other possibility, this being a microcontroller, is to use a bit of in-line assembly language to jump to the VERY beginning of the sketch, where it sets up the stack and initializes memory.
Code:
 asm("jmp __ctors_end");
(an indirect jump via the "reset" vector would probably be better...)
Logged

Connecticut, US
Offline Offline
Edison Member
*
Karma: 2
Posts: 1036
Whatduino
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The goto keyword is seen as gauche in a higher-level language, but it's really not so bad as all that.  There are cases where it improves readability.  There's no technical difference between goto in C and a jump instruction in the assembler, except for the implications on other control structures like loops and functions.
Logged

Norway@Oslo
Offline Offline
Edison Member
*
Karma: 13
Posts: 2033
loveArduino(true);
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The switch-case is essentially just a lot of gotos, many of us use that without thinking twice.
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Not that I advocate what the original poster desires but I believe the following, untested and from memory, code should work as desired!

Code:
#include <setjmp.h>

jmp_buf g_there;

void error(command)
{
    while ( true )
    {
        if ( command == continue )
            break;
        else if ( command == restart )
        {
            longjmp(g_there, 1);
        }
    }
}

void setup()
{
}

void loop()
{
    int     jmp_return_value    = 0;

    // first time thru loop 'setjmp(g_there)' return 0
    
    if ( jmp_return_value = setjmp(g_there) )
    {
        // we've been called by 'longjmp', maybe do something special
        // depending upon value of 'jmp_return_value'
       setup();
       
        ...
    }
    
    // continue as normal
    ...
}
« Last Edit: June 11, 2010, 07:57:07 pm by lloyddean » Logged

Pages: [1]   Go Up
Jump to: