Common mistakes of new Geos programmers
EC coding to catch bugs 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:
LMem (chunk, huge array, DB, etc.)
- +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 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
- +high Simply increases the level of lmem checking.
- +vm Checks VM file consistency +vmemDiscard Forces
clean VM blocks to be discarded when unlocked.
- +analVMExtensive VM memory checking.
- +graphics Checks gstrings and similar graphics stuff
- +segment Extensive segment checking
- +text Performs extra error checking on Text objects
- 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.
- 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.
- Make sure to check for failed memory allocations or locks. (This can
be determined by checking for NullHandle or null pointer.)
- Don't let object resources get too big (break out into multiple
- 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
- 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
create and you try to access the file, it will crash the system.
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 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
- 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
- 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.
- 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.
- For standard menus (like "File" or "Edit") use
ATTR_GEN_INTERACTION_GROUP_TYPE = GIGT_????_MENU
Last modified: Mon Dec 22 16:55:20 PST