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

Common programming mistakes of Geos neophytes




The following is a list of common mistakes commited by programmers
who are new to Geos.  

1. Not using EC code to catch errors
   Since Geos is multithreaded and unlocked memory blocks can be moved
   out from under a pointer, debugging memory scribbling is quite
   difficult.  Become familiar with the EC routines that are available
   within Geos and use them liberally.  When compiled as non-EC, these
   routines become empty stubs, so they won't impact the performance of
   the shipping version of your application.

   Related to this is stress testing your application with swat.  By
   simply turning on many of the EC flags, you can find many bugs that
   would otherwise take days to find and duplicate.  Here is a partial
   list of flags to set:

   General Memory
	+unlockMove
	  Force unlocked blocks to move whenever possible.  This
	  causes memory leaks to be more consistently reproducable.
	+free
	  Checks free blocks on the heap, which normally
	  should contain 0xCC. If they don't, a fatal
	  error is generated, and information about the
	  previous blocks on the heap are dumped.
	  
	  The previous block is useful because often you
	  will just be writing past the end of a block.
	  Often you can just figure out what this previous
	  block is, and then track the bug looking at the
	  code.

   LMem (chunk, huge array, DB, etc.)
	+lmem
	  Checks the lmem internal structures. If you
	  find that an LMBH_handle (or another header
	  field) is messed up, this is frequently useful
	  for finding out when it is happening.
	+lmemMove
	  Force lmem blocks to move whenever possible
	+high
	  Simply increases the level of lmem checking.

   VMFiles
	+vm
	  Checks VM file consistency
	+vmemDiscard
	  Forces clean VM blocks to be discarded when unlocked
	+analVM
	  Extensive VM memory checking

   Miscellaneous
	+graphics
	  Checks gstrings and similar graphics stuff
	+segment
	  Extensive segment checking
	+text
	  Performs extra error checking on Text objects

2. Variables
   - Global variables, static variables and static strings take up
     space in dgroup.  dgroup is a fixed block, so the bigger it gets 
     the more grief it causes the memory manager.  Move as much of
     statics and globals to object instance data or chunks in a data 
     block.

   - Local variables are stored on the stack.  This is only a bad thing
     when you have a local variable that is a huge structure or array
     (10s or 100s of bytes) because it could cause the stack to overflow.
     To reduce the size of variables on the stack, change the variable
     to a handle, optr, or ptr to a block or chunk that contains the
     structure.

     You can see the value of the stack pointer register for each frame
     on the stack by doing "backtrace -rsp" in swat.

3. Memory
  - Make sure to check for failed memory allocations or locks.  (This can
    be determined by checking for NullHandle or null pointer.)
  - Don't allocate many memory blocks for small data structures.  Each 
    block takes up a global handle (of which there are usually only 3000
    total) so don't create many blocks that each hold a small amount of
    data.  This will eat away at the global handle table and can lead 
    to crashes or other memory problems.
  - Don't let object resources get too big (break out into multiple resources)
  - In a method handler, pself can be invalidated after calling another 
    message or when performing an LMem action on the obj block (oself).
    Make sure to re-dereference pself (with ObjDerefGen or ObjDerefVis)
    when using it after one of these invalidating actions.  On the other
    hand, don't overkill by dereferencing after every routine call, too.
    (Note, this has changed for products after the N9000; see @self.)
    
4. Threads
  - Do not allow your application's ui thread to make calls to its process
    thread.  This can result in deadlock because the process thread must
    occasionally make calls to the ui thread.
  - All objects in a Gen tree must be run by the same thread (usually the
    ui thread).

5. Files
  - Always check for successful file open/create.  You can simply check
    if the returned FileHandle is NullHandle.  If the file could not be
    opened or created and you try to access the file, it will crash the
    system.

6. UI and Generic object trees
  - The GenProcessClass has no instance data. NONE! It is a hybrid 
    class that has no space allocated for instance data. If you try to give
    it instance data you are guaranteed to get memory scribbling errors.
  - Remember to use the neverSaved flag on ProcessClass @classdecl.  Do 
    not use this flag on objects that have instance data unless the
    object is marked ignoreDirty.
  - Don't over-use HINT_DEFAULT_FOCUS or HINT_DEFAULT_TARGET.  Only one
    object at a given level in the gen tree can have the default focus 
    or target.

7. Localization
  - The resource of chunks to be localized must be marked with the lmem
    flag.  This can be done in the .gp file by adding "lmem" to the 
    resource declaration.

8. Graphics
  - Difference between a GString and a GState.  A GString is a data
    structure containing a sequence of graphics commands (see gstring.h).
    A GState contains information that keeps track of how to draw (the 
    colors, scaling, current text font, etc.).  A GState can contain a
    gstring.  A GString cannot contain a GState.

9. Miscellaneous
  - For standard menus (like "File" or "Edit") use
    ATTR_GEN_INTERACTION_GROUP_TYPE = GIGT_????_MENU