[comp.lang.pascal] Possible bug in TVision

John G. Spragge <SPRAGGEJ@QUCDN.QueensU.CA> (06/07/91)

I developed a descendant of the Turbo Vision sorted collection object
to do lookups, to find that when the program attempted to expand the
collection past the point where memory could hold it, instead of
quitting the program with an appropriate error code, as the book
says should happen, the program appeared to use a nil pointer as if
it was real, with the usual results (total system lockup).

I seem to have avoided this problem by checking to make sure I do not
try to add any objects there is no room for to the collection. I have
also designed an override for the default memory grabber in the
collection object. This seems to be an effective work around.

--------------------------------------------------------------------
(*  Code distributed utterly without warranty of any kind. The
 *  program it solves may well exist only on my machine. The
 *  code herein may only solve it on my machine. Here goes anyway...
 *)

TYPE
   TFixedColl  =   OBJECT (TSortedCollectioN)
                        PROCEDURE SetLimit  { gen. new pointer list    }
                        (
                         ALimit   :    INTEGER   { new size limit      }
                        );
                        VIRTUAL;
                   END;

PROCEDURE TFixedColl.SetLimit     { generate a new list of pointers    }
(
 ALimit    :   INTEGER                 { new size limit                }
);

CONST
   ps      =   SIZEOF (POINTER);       { size of pointers in bytes     }

VAR
   nl      :   PItemList;              { new collection item list      }

BEGIN          { Set Limit (in TContext) }
   IF (Count > MaxCollectionSize) THEN      { too many items requested }
       Error (coOverFlow, Count)
   ELSE
   IF (ALimit < Count) THEN                 { expand to list size      }
       ALimit := Count
   ELSE
   IF (ALimit > MaxCollectionSize) THEN     { limit to a segment       }
       ALimit := MaxCollectionSize;

   IF (ALimit = 0) THEN                     { erase the whole list     }
   BEGIN
       FREEMEM (Items, Limit * ps);
       Limit := 0
   END
   ELSE
   IF (ALimit <> Limit) AND (MaxAvail > ps * ALimit) THEN
   BEGIN
       GETMEM (nl, SIZEOF (POINTER) * ALimit);   { get new list space  }
       IF (Limit < ALimit) THEN                  { copy to new list    }
           MOVE (Items^, nl^, Limit * ps)
       ELSE
           MOVE (Items^, nl^, ALimit * ps);
       FREEMEM (Items, Limit * ps);              { release old list    }
       Limit := ALimit;                          { set the new limit   }
       Items := nl                               { store new list ptr. }
   END
   ELSE
       Error (coOverFlow, ALimit)           { crash if no space        }
END;           { Set Limit }

disclaimer: Queen's University supplies me with computer services, not
            my opinions. Also, they are in no way responsible for any
            errors in the foregoing.

John G. Spragge