[Python-Dev] Assertion failed in dictobject.c (original) (raw)

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 mafill and masize are both 8. maused 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 .

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).