[14.10] Do I need to dispose of these objects when I'm done?

In general, child objects birthed from parent scripts dispose of themselves as soon as there aren't any variables around the place referring to them: since you can't use them if you don't have a reference to them, Director takes the opportunity to trash them and reclaim the memory they used.

However, there may be cases where references are kept not in variables, but in lists or the properties of other objects. As discussed in section 12.8, if a circular reference arises (if, for example, your object keeps a reference to itself -- not as outlandish as it may seem, honest guv -- or keeps a reference to another object which in turn keeps a reference to it, etc), the memory occupied by an object may be lost to your movie permanently.

If your objects are simple, and don't cross-reference one another, it should usually be sufficient to clear out any object variables that you're no longer using. If they're kept as globals, they'll stay around until you set them to something else, or issue a clearGlobals command. If they're kept in a local variable, then they'll vanish in a puff of unsmoke as soon as the particular handler they're in exits.

However, if you (like me) sometimes find yourself using objects that contain lists of other objects which in turn contain other lists and yet more objects, any one of which may in turn refer back to the first, you'll need to institute some way of aggressively clearing them up. Here's an extravagantly over-the-top way:

    -- a generalized, recursive object/list disposal handler
    
    -- note that in most cases you'll actually want to provide
    -- a more specialized mKill (or whatever) method for each of
    -- your objects that takes into account ownership issues
    -- (ie, it only disposes of those parts of the object that
    -- the object actually controls itself, and will leave alone
    -- things that are merely references to objects under the
    -- control of some other program entity; such considerations
    -- are a matter of policy and can't be determined by a general
    -- procedure such as this)
    
    -- in addition, an mKill method would only need concern itself
    -- with the specifics whereas this goes overboard trying to
    -- handle anything that's slung at it
    
    -- the hierarchy argument is used by the recursive call, and
    -- should be left out when the handler is first called
    -- ie, usage is:
    
    --    dispose object
    
    on dispose anObject, hierarchy
      -- non-objects don't need to be disposed
      -- (lists are objects as far as objectP() is concerned)
      if not objectP(anObject) then return
      
      -- we don't need to dispose of points and rects
      if ilk(anObject, #point) or ilk(anObject, #rect) then return
      
      -- use a string to determine wayward object types
      set objStr = string(anObject)
      
      -- we don't need to dispose of casts either
      if word 1 of objStr = "(cast" then return
      
      -- windows can be disposed easily
      if word 1 of objStr = "(window" then
        close anObject
        forget anObject
        return
      end if
      
      -- xobjects likewise
      if char 2 to 7 of objStr = "Object" then
        anObject(mDispose)
        return
      end if
      
      -- I *think* that should've weeded out all stray object types
      -- but just to be on the safe side...
      if not listP(anObject) and word 1 of objStr <> "<offspring" and Â
        word 1 of objStr <> "script" then return
      
      -- check to see if we've already disposed this object
      -- in our travels, and if not add it to the list of
      -- those we've encountered so that we don't try to dispose
      -- it again (this is mainly to avoid an infinite loop if
      -- we've got a circular structure)
      if not listP(hierarchy) then set hierarchy = []
      if getOne(hierarchy, anObject) then return
      add hierarchy, anObject
      
      -- we have to treat lists and propLists differently from
      -- objects and scripts because we can't delete
      -- properties from an object
      
      if listP(anObject) and not ilk(anObject, #propList) then
        -- recursively dispose of all the objects and then
        -- remove the reference to them from the list
        
        repeat while count(anObject)
          dispose getAt(anObject, 1), hierarchy
          deleteAt anObject, 1
        end repeat
        
        return
      end if
      
      -- with propLists, there's the possibility that the property
      -- may also be an object reference (no, really...)
      
      if listP(anObject) then
        -- recursively dispose of all the objects and
        -- remove the references to them from the list
        
        repeat while count(anObject)
          set theProp = getPropAt(anObject, 1)
          dispose getAt(anObject, 1), hierarchy
          deleteAt anObject, 1
          dispose theProp, hierarchy
        end repeat
        
        return
      end if
      
      -- with scripts and their offspring, we can only clear the
      -- properties, we can't remove them, but that's sufficient
      
      if not count(anObject) then return
      
      repeat with index = 1 to count(anObject)
        set theProp = getAProp(anObject, getPropAt(anObject, index))
        dispose theProp, hierarchy
        setProp anObject, getPropAt(anObject, index), 0
      end repeat
      
    end dispose
The above handler should be able to annihilate more or less any object submitted to it, but it is wildly excessive. Disposing of every element of every list and every property of every object is *very* slow and the high level of recursion can also make it a terrible memory hog. Even for circular references, it should usually be sufficient to use more slimline disposal procedures like these:
    -- snappier disposal
    -- this is for lists only
    
    on vaporize aList
      repeat while count(aList)
        deleteAt aList, 1
      end repeat
    end vaporize
and this is for script/child objects
    
    on exterminate anObject
      if count(anObject) = 0 then return
      repeat with index = 1 to count(anObject)
        setProp anObject, getPropAt(anObject, index), 0
      end repeat
    end exterminate

This is particularly effective if used in combination with custom mKill methods for your objects -- since you'll generally know where the dangerous bits of any object are, you can handle those more thoroughly and then just wipe the properties wholesale.

Factory objects are a little different. These have to be explicitly disposed of using the built-in mDispose method:

    someObject(mDispose)
If you forget to do this, the memory used by your object won't get reclaimed. If you reset the variable that tells you where it is, you won't be able to get the memory back without quitting Director or doing a wholesale purge. So, if you do use factory objects for some reason, take care to dispose of them properly.