Article # 104, added by Geoworks, historical record
| first | previous | index | next | last |

Fixing STACK_OVERFLOW




If you are experiencing "death due to STACK_OVERFLOW", you can use the
backtrace command in Swat to view the stack usage.  In Swat, stop in
the method/routine you are concerned about and type "backtrace -rsp"
this means "show register sp for each stack frame in the backtrace".
When analyzing the stack usage, you should be concerned by any large
changes in the sp value between frames, and by sp's value nearing about
250.

There are several ways to fix the stack usage problem.  Here are some
considerations.

1) Reducing the size of local variables
==========================================================

If your routine/method has large local arrays or structures in it,
you should consider moving the array/structure to a global data
block or allocating a block dynamically (using MemAlloc).  This
concern is due to the fact that local variables are stored on the
stack, so large local variables will eat up lots of stack space.

Example:
--------
This code creates a local variable of 2 bytes to hold the handle
of a block that contains a 200-byte character string, rather than 
creating a local variable to hold the string itself (char myStr[200]).

Also, the handle is passed to another routine, instead of passing
the string itself.

   @method MyProcessClass, MSG_MY_MSG
   {
      MemHandle myStrHandle;
      char *myStr;

      myStrHandle = MemAlloc(200, HF_FIXED, HAF_LOCK);

      if ( myStrHandle == NullHandle )
      {
         return(-1);  /* return error */
      }
      else
      {
         myStr = MemDeref(myStrHandle);

         /* ... perform your code here. */

         AnotherRoutineThatNeedsTheString(myStrHandle);

         MemFree(myStrHandle);
         return(0);  /* return okay */
      }
   }


2) forceQueue'ing messages
==========================================================

For messages that are deeply embedded, @send the message with the
"forceQueue" flag.  This assures that the message will be placed on
the message queue, so it will have the full stack space when it is
Bhandled.  The syntax is: "@send, forceQueue MyObject::MSG_MY_MSG".

The reason for the forceQueue flag is that if the destination
object is run by the same thread as the calling object, then the
sent message will be handled immediately as if it were an @call.
The forceQueue flag compels the system to always put the event on
the thread's message queue so it won't be executed until after the
current code (and all the code frames on the stack) return, and
after any other events that are already on the queue have returned.
This gives the queued message the entire stack to work with.

If the message to send is somewhat time-critical, you can also add the
flag insertAtFront, which puts the event at the start of the queue,
so it gets executed before any other events in the queue.

Note that the forceQueue flag cannot be used with @call.


3) Avoid deeply-nested routine calls
==========================================================

Similar to 2) above, deeply nested routine calls will eat away at
the stack.  Try to arrange your code to avoid this -- perhaps by 
sending message (using @send, forceQueue instead), or by rearranging
how your code is called, to more routines are called from a higher
level.


4) Increasing the size of the UI stack (this only works for
   applications, not for libraries)
==========================================================

As a final option (and this should only be used as a last resort), you
can increase the size of the stacks for each thread in your application.

To change the stack size of your application's process thread, use the
"stack" keyword in your .gp file:

    stack 3000

The parameter is in bytes; the default is 2000 bytes.

To change the stack size of your application's ui thread, subclass
MSG_PROCESS_CREATE_UI_THREAD as follows:

   @method MyProcessClass, MSG_PROCESS_CREATE_UI_THREAD
   {
      stackSize = 3000;     /* set new stack size to 3000 bytes */
      @callsuper();
   }

You should use backtrace to determine the minimum increase that you
need to make to the stack.