This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: g++ 4.0.0: hash_map hangs when compiled with -O3 on AMD64

I've isolated the problem to some extent. See below.
Best regards, Paul Leopardi
On Wed, 4 May 2005 09:57 am, Paul C. Leopardi wrote:
> I'm seeing the following behaviour with GluCat 0.1.8 on AMD64.
> ( )
> ./configure --with-hash-map --enable-debug=no: compiled program hangs
> (this uses __gnu_cxx::hash_map and -O3)
> gdb on the compiled program: bt results in hundreds of stack frames.
> Looks like the stack has been corrupted.
> Also it looks like the hang or corruption happens when using iterators with
> hash_map. I've looked at the test suite and I don't see a test where
> iterators are used with hash_map.

I've now done extensive testing with the optimization options of g++ 4.0.0, 
and see that the problem only happens when both of the following flags are 
used: -fstrict-aliasing -finline-functions. 
The -O2 flag implies -fstrict-aliasing and 
the -O3 flag implies -fstrict-aliasing -finline-functions. 

Since it seems that these flags are incompatible when used with GluCat and 
__gnu_cxx::hash_map, I did some performance testing and found that the GluCat 
gfft_test is faster with -O3 -fno-inline-functions than it is with
-O3 -fno-strict-aliasing.

In gdb, using GluCat gfft_test compiled with -O3, I do not get stack 
corruption. I don't understand this. The test programs test02, test03 and 
test04 do get stack corruption.

What I see instead with gfft_test is that in a for loop which compares an 
iterator of type __gnu_cxx::hash_map::const_iterator with end(), the loop 
runs forever. 
It looks like for __gnu_cxx::hash_map::const_iterator, operator++ no longer 
works correctly when both -fstrict-aliasing -finline-functions are used.
In particular, the following routine in hashtable.h looks like it is failing 
to incement the const_iterator.

      const _Node* __old = _M_cur;
      _M_cur = _M_cur->_M_next;
      if (!_M_cur)
	  size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
	  while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
	    _M_cur = _M_ht->_M_buckets[__bucket];
      return *this;

I tried changing the routine to the following
      const _Node* __old = _M_cur;
      _M_cur = _M_cur->_M_next;
      if (!_M_cur)
          for( size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val) + 1;
               !_M_cur && __bucket < _M_ht->_M_buckets.size();
            _M_cur = _M_ht->_M_buckets[__bucket];
      return *this;

In gdb it looks like the same error is happening, but it is now a little 
easier to see what happens to __bucket. In my particular case, at the 
initialization of the for loop, the expression
_M_ht->_M_bkt_num(__old->_M_val) should have the value 1, but when I examine 
__bucket, I see that it has the value 1, not 2 as I expected.

Unfortunately, I still don't have a short test case. I tried adding a loop 
with __gnu_cxx::hash_map::const_iterator to the libstdc++/14648 test program, 
and failed to reproduce the problem.

Do I have enough info to file a bug report or do I still need to try to create 
a short test case?

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]