When you pass a static temp-table from one procedure to another using the static TABLE parameter form, either locally or remotely, the AVM takes care of deleting the temp-table and its contents when the procedure that defines it is deleted, just as it does for other static objects.

However, if you pass a temp-table through a TABLE-HANDLE, then you are creating a dynamic copy of the temp-table. Whether there is a static temp-table definition for it on one side of the call or the other, the TABLE-HANDLE parameter creates a dynamic temp-table. If a procedure passes a temp-table to another procedure using the INPUT TABLE-HANDLE form, then the calling procedure must take responsibility for deleting the temp-table when it’s done with it.

If a procedure receives a temp-table from another procedure using the OUTPUT TABLE-HANDLE form, then the receiving procedure must delete its copy of the temp-table after it is done with it. For example:
RUN getCustomers(OUTPUT TABLE ttCustomer).
...

PROCEDURE getCustomers:
  DEFINE OUTPUT PARAMETER TABLE-HANDLE phTempTable.
  ...
  /* dynamic temp-table created */
  ...
  DELETE OBJECT phTempTable.
END PROCEDURE.
Note: The DELETE OBJECT statement is not executed immediately for a dynamic TABLE-HANDLE parameter. The delete is actually delayed until after the temp-table has been copied back to the caller.

As with other dynamic objects, the AVM does not know when you are done with a dynamic copy of a temp-table and therefore cannot delete it for you. You cannot allocate a temp-table to a widget pool, so this mechanism does not help you out. The temp-table is created in the SESSION widget pool and therefore stays there until it is deleted or until the session ends. Because a temp-table is normally a much larger object than a dynamic button, query, or buffer, it is critically important that you delete temp-tables when you are done with them. If you are done with the data in the temp-table but need to use the table again, then use the EMPTY-TEMP-TABLE() method on the table handle to remove the data. Delete the table itself using the DELETE OBJECT statement when you are done with it altogether.

Because dynamic temp-tables are allocated in the SESSION pool, you can locate them through the SESSION handle’s buffer chain. If the buffer has a valid TABLE-HANDLE attribute, then it is a temp-table buffer and its TABLE-HANDLE points to the temp-table itself:
DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO.

hBuffer = SESSION:FIRST-BUFFER.
REPEAT WHILE VALID-HANDLE (hBuffer):
  IF VALID-HANDLE (hBuffer:TABLE-HANDLE) THEN
    DISPLAY hBuffer:NAME WITH FRAME F 10 DOWN.
  hBuffer = hBuffer:NEXT-SIBLING.
END.

Use the NUM-REFERENCES attribute

Before you delete a procedure, you can use the NUM-REFERENCES attribute to determine whether a temp-table is serving as a reference for other temp-tables in some other procedure. This is particularly helpful when you pass temp-tables as parameters with the BIND keyword. Use this syntax:
integer-var = table-handle:NUM-REFERENCES.

If the temp-table has no other temp-table definitions currently referencing it, the NUM-REFERENCES attribute returns 0. If one or more temp-tables are still being used by another temp-table, then NUM-REFERENCES returns the number of referring temp-tables.

You can also use NUM-REFERENCES to debug any memory leaks that occur when a persistent procedure closes.