Announcement

Collapse
No announcement yet.

Stack Problem?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Stack Problem?

    Hello, i am having an issue i have never encountered before. I am running a simulation program (PB CC 6.04) that runs hundreds of thousands of iterations of the simulation. After a certain number of times through the program would crash (250k iterations). I tracked every variable in the program and i did not overflow a data limit (integer > allowable for example), or call on array outside its dimension. I tired using the debugger with limited success, but i saw a statement about STACK being full? So i added the following:
    Code:
    #STACK 10000000
    Now the program runs 2.5 Million iterations without crashing, 10x more

    i changed the stack to 100 Mb, and the program runs 25 million iterations without crashing, 10x more

    What is going on? Is there a way to clear the stack from inside the program to prevent this?

  • #2
    Hi Larry,
    I've generally avoided stack issues by using Global variables, whose byte limits are much larger.

    Comment


    • #3
      If you are using recursion your stack problem may be connected to that.
      Walt Decker

      Comment


      • #4
        Problem code not shown, but Walt is probably correct - this is usually the result of deep recursion.
        Alternatively, are you using a lot of concurrent threads?

        To answer your question, no you can't "clear the stack" other than by closing the threads or unrolling the deep recursion that is using that amount of stack space.


        Comment


        • #5
          You should never attempt to clear the stack.
          It's better to find what's causing the problem in the first place.
          Something must be put on the stack which is not being removed.

          Can you not track down what that is?
          You can look at the value of the stack pointer. Maybe that'll help track down where the problem occurs:

          Code:
          GLOBAL StackPointerValue AS LONG
          
          FUNCTION PBMAIN () AS LONG
          
          !mov StackPointerValue,esp  'get the stack pointer
          
          PRINT StackPointerValue
          
          WAITKEY$
          
          
          END FUNCTION

          Comment


          • #6
            hmmm

            Have I learned something????

            Could someone please finish the sentence 'Kerry you have to use stack whenever you....'
            [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
            Kerry Farmer

            Comment


            • #7
              Could someone please finish the sentence 'Kerry you have to use stack whenever you....'...
              Whenever you store a local variable, call a function, expect an interrupt..

              Local variables are stored on the stack.
              The return address for all function calls is stored on the stack.
              If something interrupts your code, the machine state at the point of the interrupt is stored on the stack so it can be restored to resume processing at the point after the interrupt.

              Comment


              • #8
                Just to expand a little, a 32 bit executable file start with a default 1 meg stack although this can be changed if necessary. In most instances this is more than enough unless you are using very deep recursion which can go off the end of the allocated stack memory and you get a crash. Paul has given you the normal stack usage and with a high level language you really only need to keep track of stack usage with recursion as PB handles almost all stack conditions as a high level language should.

                With lower level assembler code you regularly use PUSH and POP and must do them in the right order to keep the stack balanced. The are many tricks in assembler using the stack but the fastest code avoids it as it faster in many instances to do it a different way.
                hutch at movsd dot com
                The MASM Forum

                www.masm32.com

                Comment


                • #9
                  Hi, and thanks to everyone for their thoughts. Your direction was correct, i accidentally did jump out of a subroutine before returning properly, and then called the subroutine again....

                  So i was nested 250,000 levels deep in recursion. All fixed now. I guess there is a valid reason not to use those darn GOTO commands to handle program flow.

                  Comment


                  • #10
                    Nothing wrong with "GOTO". In ASM that is used a great deal although it is "JMP". Just be careful.

                    Sometimes it is easier and more meaning-full to use a "GOTO" in a nested "FOR", "DO" or "IF" than "EXIT"
                    Walt Decker

                    Comment


                    • #11
                      Originally posted by Walt Decker View Post
                      Nothing wrong with "GOTO". In ASM that is used a great deal although it is "JMP". Just be careful.

                      Sometimes it is easier and more meaning-full to use a "GOTO" in a nested "FOR", "DO" or "IF" than "EXIT"
                      <RANT>
                      GOTO, GOSUB and Sub routines were useful constructs in early versions of BASIC before Functions and Procedures were available. Unfortunately heavy use of them almost invariably leads to error prone, difficult to debug/manage/enhance "spaghetti code". (Plenty of examples pasted right here in these forums )

                      With modern BASICs including PB, there are a very limited number of valid use cases for them. About the only one I can think of is for time critical code sections that must be repeated thousands or millions of times. Apart from that situation, the minor overhead involved in calls to Function and Procedure calls is FAR outweighed by the benefits of thos constructs.

                      Anyone still making regular use of GOTO, GOSUB and sub routines really needs to rethink their whole programming paradigm and learn to use a more structured approach.
                      </RANT>

                      Comment


                      • #12
                        I have always laughed at comments about "Spaghetti Code" when very few have ever written it and would not know how to write it. You cannot have any logic in a computer program without branching and branching lives in the realm of unconditional jumps, conditional jumps and the CALL / RET notation. To write "Spaghetti Code" means to write line numbered BASIC where you branch with the GOTO instruction back or forward to the line number labels.

                        Here is how to avoid using GOTO.
                        Code:
                        ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                        
                            MACRO Go2 = ! jmp
                        
                        ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                        
                         FUNCTION PBmain as LONG
                        
                            LOCAL var as DWORD
                        
                            Go2 lbl
                        
                            ! xor eax, eax
                            ! mov eax, [eax]        ; instant crash
                        
                            lbl:
                        
                            StdOut "How D"
                        
                            waitkey$
                        
                         End FUNCTION
                        
                        ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
                        hutch at movsd dot com
                        The MASM Forum

                        www.masm32.com

                        Comment


                        • #13
                          Spaghetti Code, [The REAL McCoy].

                          Code:
                          0000:FUNCTION PBmain as LONG
                          0001:LOCAL var as DWORD
                          0002:var = 10
                          0003:StdOut str$(var)
                          0004:var=var-1
                          0005:IF var > 0 goto 0003
                          0006:StdOut "That's all folks"
                          0007:waitkey$
                          0008:End FUNCTION
                          Clear as mud.
                          hutch at movsd dot com
                          The MASM Forum

                          www.masm32.com

                          Comment


                          • #14
                            Here are two examples of what I mean:
                            Code:
                            IF A = B THEN
                              IF B = C THEN
                                 IF C = D THEN EXIT
                                 some stuff
                              END IF
                              other stuff
                            END IF
                            The "C = D THEN EXIT" statement is fine, if you want to do "other stuff" because the "EXIT" only jumps out of the inner block and PB does not allow EXIT, EXIT in an "IF" statement. Therefore, to get out of the entire IF block you have to use a GOTO:
                            Code:
                            IF A = B THEN
                              IF B = C THEN
                                 IF C = D THEN GOTO EndThisBlock
                                 some stuff
                              END IF
                              other stuff
                            END IF
                            
                            EndThisBlock: '
                            Code:
                            FOR I = 1 TO 1000
                              FOR J = 1 TO 1000
                                FOR K = 1 TO 1000
                                  EXIT, EXIT
                               NEXT K
                              NEXT J
                            NEXT I
                            The EXIT, EXIT jumps out of the 2 inner loops. However, it is easier to maintain code because the meaning is more clear by using a GOTO:

                            Code:
                            FOR I = 1 TO 1000
                              FOR J = 1 TO 1000
                                FOR K = 1 TO 1000
                                  GOTO FindNext
                               NEXT K
                              NEXT J
                              FindNext: '
                            NEXT I
                            Walt Decker

                            Comment


                            • #15
                              I have to admit that i find the style Walt uses above more clear and this is how i prefer to get out of nested conditions. I think the multiple EXIT commands are not as clear.

                              I would express this situation as:

                              Code:
                              IF programming_style_A <> programming_style_B THEN
                                      GOTO controversy
                              END IF

                              Comment


                              • #16
                                Originally posted by Walt Decker View Post
                                The "C = D THEN EXIT" statement is fine, if you want to do "other stuff" because the "EXIT" only jumps out of the inner block and PB does not allow EXIT, EXIT in an "IF" statement.
                                ..

                                Code:
                                FOR I = 1 TO 1000
                                FOR J = 1 TO 1000
                                FOR K = 1 TO 1000
                                EXIT, EXIT
                                NEXT K
                                NEXT J
                                NEXT I
                                The EXIT, EXIT jumps out of the 2 inner loops. However, it is easier to maintain code because the meaning is more clear by using a GOTO:
                                You contradict yourself. Can you provide a compilable example that illustrates your first contention?



                                Comment


                                • #17
                                  Mr. McLachlan:

                                  You have completely misquoted. Read my post again and pay particular attention to the second FOR/NEXT example.
                                  Walt Decker

                                  Comment


                                  • #18
                                    Originally posted by Walt Decker View Post
                                    Mr. McLachlan:

                                    You have completely misquoted. Read my post again and pay particular attention to the second FOR/NEXT example.
                                    I didn't misquote, I quoted you exactly

                                    However I did misread. I missed the fact that you did not have a conditional in your third and fourth examples,so statements about IF.. EXIT... END IF in that case are moot.

                                    So you are not contradicting yourself, you are just making two separate incorrect statements.
                                    You apparently have misunderstood what EXIT does - it terminates a "loop construct". IF...END IF is NOT a "loop construct" and EXIT will not "jump out of the inner block"...

                                    Your statement "The "C = D THEN EXIT" statement is fine" is incorrect for your first example. That line will not compile in your first example since there is no loop involved. The compile will fail with a "Error 448: DO loop expected" message since the EXIT is not inside any form of loop.

                                    Your statement "PB does not allow EXIT, EXIT in an "IF" statement." is also incorrect. Here's a compilable example which does that.

                                    Code:
                                    #COMPILE EXE
                                    #DIM ALL
                                    FUNCTION PBMAIN () AS LONG
                                    LOCAL x,y,z AS LONG
                                    FOR x = 1 TO 3
                                        FOR y = 1 TO 3
                                              z = x * y
                                              IF z > 3 THEN EXIT,EXIT
                                        NEXT
                                    NEXT
                                    ? USING$ (" ## ## ##", x,y,z)
                                    END FUNCTION

                                    Comment


                                    • #19
                                      I think that we sometimes get lost in the weeds in the periodically-recurring "jump" discussion. Some people believe that GOTO/GOSUB are evil and should be avoided at all costs - including, possibly, more complicated code. I find them useful in limited situations - such as jumping out of necessarily complex code blocks. Used judiciously, they provide an excellent method of moving around code in a readable fashion.

                                      So, the earlier quote "Anyone still making regular use of GOTO, GOSUB and sub routines really needs to rethink their whole programming paradigm and learn to use a more structured approach" initially got my attention - in a bad way. I make regular but infrequent use of GOTO/GOSUB and like to think that my code is pretty structured. Know your tools and use them correctly.

                                      Comment


                                      • #20
                                        I have been hearing claptrap like this for many years. "Anyone still making regular use of GOTO, GOSUB and sub routines really needs to rethink their whole programming paradigm and learn to use a more structured approach". Now what proponents of this nonsense don't tell you is it comes at a price, far less flexibility, performance degradation and bloated code. This may have been the techniques suitable for Visual Basic of old but when you use a decent binary compiler you are wasting its real power by aping Visual Basic.

                                        High level languages usually have a number of pre-canned loop designs, FOR loops, DO loops, WHILE loops etc .... and in the task they are designed to perform, they work OK but try and do something clever like a multi entry, multi exit loop or even better, a cross fire loop. This is where a lower level, programmer loop comes to the for.

                                        As far as GOTO and GOSUB / RETURN, these are incredibly efficient techniques of working within the scope of a procedure while maintaining the full range of variables within that scope without any clunky additional overhead. They are there in the language for use and they work just fine.

                                        GOTO = JMP
                                        GOSUB = CALL
                                        RETURN = RET

                                        It really IS that simple.
                                        hutch at movsd dot com
                                        The MASM Forum

                                        www.masm32.com

                                        Comment

                                        Working...
                                        X