[Python-Dev] Assertion failed in dictobject.c

Tim Peters tim.one@home.com
Wed, 23 May 2001 16:32:04 -0400


[Jack Jansen]
> I'm seeing the assert on line 525 in dictobject.c (revision 2.92)
> failing. The debugger tells me that ma_fill and ma_size are both 8.
> ma_used is 2, and interestingly hash is also 8.

You wouldn't happen to have a reproducible test case?  That hash==8 is almost
certainly a red herring -- or a sign of wild stores <wink>.

> Going back to revision 2.90 fixes the problem (or masks it).

Instead of:

	assert(mp->ma_fill < mp->ma_size);

this code used to be:

	if (mp->ma_fill >= mp->ma_size) {
		/* No room for a new key.
		 * This only happens when the dict is empty.
		 * Let dictresize() create a minimal dict.
		 */
		assert(mp->ma_used == 0);
		if (dictresize(mp, 0) != 0)
			return -1;
		assert(mp->ma_fill < mp->ma_size);
	}

so the dict would get resized whenever ma_fill >= ma_size, although the code
only *expected* that to happen when the dict table was NULL.  It was perhaps
happening in other cases too.  The dict is never empty (NULL) after the
patch, so the special case for "empty" got replaced by an assert.

Offhand I don't see how this could be triggering -- although *something*
about the 2.90 logic makes me uneasy!  Ah, mp->ma_fill >= mp->ma_size wasn't
a correct test:  filled slots that aren't used slots don't stop a new key
from being added.  Assuming that's it, 2.90 could do needless calls to
dictresize, but the new version does a bogus assert instead.  So replace the
current version's offending

	assert(mp->ma_fill < mp->ma_size);

with

	assert(mp->ma_used < mp->ma_size);

Let me know whether that solves it.

2.90 may also suffer a bogus

		assert(mp->ma_used == 0);

failure.  It's not easy to provoke any of this, though (requires exactly the
right sequence of mixed inserts and deletes, with hash codes hitting exactly
the right dict slots).