Hello,

There appears to be an error in HashTable::expandWatching in hash.cpp.

This problem can be reproduced by setting the initial value of the
dictionary
(#define PROC_DICTIONARY_LOGSIZE in proc.h) to some very small value
(e.g. 4) in order to force the hash table to be resized by even a small test
case.

There are actually three bugs.

(a) if an item which is not the final item in the old bucket is moved to the
new bucket in the upper half AND it is the final item in the new bucket then
its next pointer is left pointing to the item which followed it in the old
bucket.

(b) if all the items in an old bucket are moved to a new bucket then the old
bucket's pointer is never reset to NULL, so it will point to the head of the
items in the new bucket.

(c) When (a) and (b) are fixed one discovers that the dictionary is
initialized
twice - once by the ctor and once by prepareForRun().  The double
initialization causes twice as many buckets to be allocated as expected
so that logSize and bucketCount are out of sync and this causes
expandWatching to place the new items in the wrong bucket.

Fix for (c) in proc.cpp:prepareForRun() near line 202:
------------------------------------------------------------------------
   old:  dictionary.initialize();
   new: dictionary.destroy(); dictionary.initialize();

Fix for (a) and (b) in hash.cpp:expandWatching near line 186:
----------------------------------------------------------------------------
-------
    for (i = 0; i < oldBucketCount; i++)
    {
        upperTail = lowerTail = NULL;
        for (p = buckets[i]; p; p = p->next)
        {
            if (p -> code & distinguish)
                chain(p, upperTail, i + oldBucketCount)
            else
                chain(p, lowerTail, i);
        };
  if (lowerTail == NULL) {
   buckets[i] = NULL;
  }
  else {
   lowerTail->next = NULL;
  }
  if (upperTail != NULL) upperTail->next = NULL;





Reply via email to