http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51845

--- Comment #17 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-18 
18:51:57 UTC ---
I think the bug is in the two argument erase in hashtable.h.
In the testcase we are removing two elements, the last element from bucket 10
and first element from bucket 20, but there is also another element in bucket
20.
This means that __is_bucket_begin is false initially, the last element from
bucket 10 is removed, then __is_bucket_begin is set to true, but as we don't
remove the whole bucket (we stop when __n_bkt == __bkt because we reach
__last_n), the _M_remove_bucket_begin call does nothing.  But as __n_bkt ==
__bkt, we dont' update _M_buckets[__n_bkt], so it references a removed node.

--- libstdc++-v3/include/bits/hashtable.h    2012-01-15 20:59:53.765526939
+0100
+++ libstdc++-v3/include/bits/hashtable.h    2012-01-18 19:49:39.222388730
+0100
@@ -1541,7 +1541,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __bkt = __n_bkt;
     }

-      if (__n && __n_bkt != __bkt)
+      if (__n && (__n_bkt != __bkt || __is_bucket_begin))
     _M_buckets[__n_bkt] = __prev_n;
       __prev_n->_M_nxt = __n;
       return iterator(__n);

seems to fix this and I think it should be safe, when __is_bucket_begin is set,
it means __n will be the bucket begin, so _M_buckets[__n_bkt] should be
__prev_n.
The __n_bkt != __bkt test is still needed, for the case where we remove just
the trailing elements of some bucket, then we want to update the next bucket,
even when __is_bucket_begin is false.

Reply via email to