stack overflow error

  • Hello Everyone,


    working on a R200iA, with a Rj3iB teach pendant.


    My issue is after the robot runs for 3-4 hours i am getting a stack overflow.


    i have already increased the size to 4000, but that has not corrected my issue.


    I am putting my programs here for some help diagnosing the issues.


    I may not be the best programmer or have things worded properly, but it works(mostly).


    I have seen the error in the conv_igt, and also in the Prog14001 programs.


    please help.


    thanks
    Chris









  • Line 26 of EJ_REAR calls CONV_IGT, line 53 of CONV_IGT calls EJ_REAR. You need to get rid of this recursive call.


    thanks, i did see this but i cant think of another way to call these programs.


    26: IF R[19:MOLD NUMBER]=14001 OR R[19:MOLD NUMBER]=14016,CALL CONV_IGT ;
    calls a program based on register value, in which it is in this program, how else should I call this program up based on a register value ?


    53: IF R[18:REAR EJECT 1]=1,CALL EJ_REAR ;
    restarts the sequence, without this(I tried a jump label around it) the program just waits.

  • It would help me to understand if I knew what your main program is the general sequence, but I will take a stab at it.


    It appears that you are using a call statement to "restart" the sequence as you stated, which is not the correct method. Say you have Program A which calls Program B. When Program B is finished it will automatically resume on the next line of code in Program A. If Program A needs to repeat then there should be logic in Program A that Jumps back up, so it restarts itself.


    When you have another program "restarting" your sequence by making a recursive call, what you are actually doing is creating a new instance of that program, without ever ending the previous instance. Over time these instances build up until you have hundreds of them and the robot controller runs out of memory. You should not call a program that already exists on the call stack, because that will generate a new instance of that program. Instead you need to let the sub-program's finish to get back up to the original calling program.


  • It would help me to understand if I knew what your main program is the general sequence, but I will take a stab at it.


    It appears that you are using a call statement to "restart" the sequence as you stated, which is not the correct method. Say you have Program A which calls Program B. When Program B is finished it will automatically resume on the next line of code in Program A. If Program A needs to repeat then there should be logic in Program A that Jumps back up, so it restarts itself.


    When you have another program "restarting" your sequence by making a recursive call, what you are actually doing is creating a new instance of that program, without ever ending the previous instance. Over time these instances build up until you have hundreds of them and the robot controller runs out of memory. You should not call a program that already exists on the call stack, because that will generate a new instance of that program. Instead you need to let the sub-program's finish to get back up to the original calling program.


    Alrighty,


    i have it so when i push user 1


    then it calls EJCT_F_R



    then if a register 17 or 18 would equal 1 it would then call a different program



    then since R 19 equals 14001, it would call that program.



    then it calls conv_igt based on R 19 from the EJ_rear program



    then it re-calls the programs all over again.


    can you provide further direction ?

  • It still looks like you might get into a situation with the recursion. You call EJ_rear which calls conv_igt which calls EJ_rear again and so on and so on. Execution memory stack is allocated when you call as HawkME said an "instance" of the program. That allocation remains in effect until the program finishes and returns from where it was called. If you call a program which calls the same program which called it, and the it calls the same program it is known as being recursive. Memory continues to be allocated, but not freed, because you are not letting the programs finish, thus clearing the memory allocation.

  • EJ_REAR is already in the call stack, so you just need to let it naturally get back to it.


    1. Delete line 50-53 in CONV_IGT, that logic is a high-level decision that needs to be made at a top level. That logic already exists in the EJCT_F_R program and is the only place it should exist.


    2. Now after CONV_IGT finishes you go back to the line 27 of EJ_REAR, which will finish and go back to line 15 of EJCT_F_R.


    3. You need to add a JMP LBL at line 15 of EJCT_F_R to go to a previous spot in the program where you want to start. This could be LBL 2, or if you want to start over at the top of EJCT_F_R, add another label at the very beginning.



    So with these changes you should see that your top level program "EJCT_F_R" only has 1 instance, and will continue to loop until ABORTIT is called. And in fact all of the other programs will only create 1 instance at a time. Whenever you hit the /END in your program, it will destroy that instance.

    Edited once, last by HawkME ().

  • 2. Now after CONV_IGT finishes you go back to the line 27 of EJ_REAR, which will finish and go back to line 15 of EJCT_F_R.3. You need to add a JMP LBL at line 15 of EJCT_F_R to go to a previous spot in the program where you want to start. This could be LBL 2, or if you want to start over at the top of EJCT_F_R, add another label at the very beginning.



    So with these changes you should see that your top level program "EJCT_F_R" only has 1 instance, and will continue to loop until ABORTIT is called. And in fact all of the other programs will only create 1 instance at a time. Whenever you hit the /END in your program, it will destroy that instance.


    Okay, thanks.


    That is done and it is running still.


    However, doesn’t putting a jump label at the bottom of a program and the label at the top also make a loop, because it will never hit that end.


    Just asking because I am still learning and this has helped me tremendously.


    Appreciate it.


    Chris

  • This is OK looping at the higher level because it is only the one instance of this program. It is not the looping that is the problem, but the calling over and over programs which don't terminate. The memory for those programs doesn't free up. That is what is causing your stack overflow.


  • This is OK looping at the higher level because it is only the one instance of this program. It is not the looping that is the problem, but the calling over and over programs which don't terminate. The memory for those programs doesn't free up. That is what is causing your stack overflow.


    thanks for the explanation.


    I will report back if i hear it goes down again.

  • The only way your current program ends is if the condition is met to call the ABORTIT program.
    11: SELECT R[19:MOLD NUMBER]=0,CALL ABORTIT ;
    12: IF R[17:FRONT EJECT 1]>=1 AND R[18:REAR EJECT 1]=1,CALL ABORTIT ;


    Usually I will add a Stop push button that goes to a DI. Then in your program loop you can add "IF DI[], JMP LBL 999". Put Label 999 at the end of the program. Or you could do "IF DI[], CALL ABORTIT". I'm not sure what your ABORTIT program entails, but I assume it aborts the program, maybe other stuff too.

    Edited once, last by HawkME ().


  • The only way your current program ends is if the condition is met to call the ABORTIT program.
    11: SELECT R[19:MOLD NUMBER]=0,CALL ABORTIT ;
    12: IF R[17:FRONT EJECT 1]>=1 AND R[18:REAR EJECT 1]=1,CALL ABORTIT ;


    Usually I will add a Stop push button that goes to a DI. Then in your program loop you can add "IF DI[], JMP LBL 999". Put Label 999 at the end of the program.


    But a FCTN and abort all, will end all programs, right ?


    and any "fault" will end all programs, right ?


    i currently have a BG program running, should i add to it stating that if SO(fault light) to call abort it ?

  • FCTN>Abort All will abort all programs.


    A fault will usually just pause the program, not abort it. You could then press reset and resume. However, since you are triggering this all with a User Key and Macro, I don't believe you can resume from a fault. That is one of the reasons why I do not use Macro's.


  • FCTN>Abort All will abort all programs.


    A fault will usually just pause the program, not abort it. You could then press reset and resume. However, since you are triggering this all with a User Key and Macro, I don't believe you can resume from a fault. That is one of the reasons why I do not use Macro's.


    i think i was updating my post when you made this reply.


    yea, i dont think i can restart a program.


    and this is from above.
    i currently have a BG program running, should i add to it stating that if SO(fault light) to call abortit ?


    that should kill all running as well ?

  • hi guys,


    well it is still getting a stack overflow error. Would you mind reviewing my updated code ?


    thanks
    Chris







  • I don't see your code for EJ_Front, so I am guessing that maybe you had it set up like rear and have the recursive calls in there too?


    thanks for looking, here is Ej_front.


    however, it pulls either front or rear based on a register value.


  • I am kind of at a loss now. The next best thing that I can suggest is kind of tedious; Step through line by line so you can see exactly what is causing the issue. Or, put pauses where you think is a strategic point in the program, and then step through.


  • I am kind of at a loss now. The next best thing that I can suggest is kind of tedious; Step through line by line so you can see exactly what is causing the issue. Or, put pauses where you think is a strategic point in the program, and then step through.


    I will step through the entire program, making sure that it hits the end in each.


    thanks.
    Chris

Advertising from our partners