Assertion failed in dictobject.c

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. Going back to revision 2.90 fixes the problem (or masks it). -- Jack Jansen | ++++ stop the execution of Mumia Abu-Jamal ++++ Jack.Jansen@oratrix.com | ++++ if you agree copy these lines to your sig ++++ www.oratrix.nl/~jack | ++++ see http://www.xs4all.nl/~tank/ ++++

[Jack Jansen]
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).

[Jack Jansen]
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).
participants (2)
-
Jack Jansen
-
Tim Peters