This is the mail archive of the gcc-bugs@gcc.gnu.org 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]

[Bug libstdc++/17664] New: Crash in std::map when using _GLIBCXX_DEBUG with multithreading


There is a (multithreaded) condition where the STL behaves different if 
compiled with or without _GLIBCXX_DEBUG. If _GLIBCXX_DEBUG is defined the 
attached program crashes. To compile the attached program the ACE 
(http://www.cs.wustl.edu/~schmidt/ACE.html) library which can be downloaded at 
http://deuce.doc.wustl.edu/Download.html is needed. 
 
I suspect that the iterators make some modifications on the map they iterate 
on if _GLIBCXX_DEBUG is defined. This leads to different (and in this case 
erroneous) behavior in multithreaded applications. 
 
Lothar 
 
--------------------------------- cut --------------------------------------- 
/* 
# compile without _GLIBCXX_DEBUG 
lothar@janus-w$ g++ -V 3.4.1 -O0 -g -I ${ACE_ROOT}/ -L ${ACE_ROOT}/lib/ -lACE 
-lstdc++ -lpthread -lrt -ldl bug.cpp -o bug 
lothar@janus-w$ LD_LIBRARY_PATH=${ACE_ROOT}/lib ./bug 
lothar@janus-w$ 
 
# compile with _GLIBCXX_DEBUG but guard with a write lock 
lothar@janus-w$ g++ -V 3.4.1 -O0 -g -D_GLIBCXX_DEBUG -I ${ACE_ROOT}/ -L 
${ACE_ROOT}/lib/ -lACE -lstdc++ -lpthread -lrt -ldl bug.cpp -o bug 
lothar@janus-w$ LD_LIBRARY_PATH=${ACE_ROOT}/lib ./bug 
lothar@janus-w$ 
 
# compile with _GLIBCXX_DEBUG (crashes) 
lothar@janus-w$ g++ -V 3.4.1 -O0 -g -D_GLIBCXX_DEBUG -DCRASH -I ${ACE_ROOT}/ 
-L ${ACE_ROOT}/lib/ -lACE -lstdc++ -lpthread -lrt -ldl bug.cpp -o bug 
bug.cpp:19:2: warning: #warning will crash 
lothar@janus-w$ LD_LIBRARY_PATH=${ACE_ROOT}/lib ./bug 
Segmentation fault 
lothar@janus-w$ 
 
*/ 
 
#include <algorithm> 
#include <map> 
 
#include "ace/Task.h" 
#include "ace/Barrier.h" 
 
#define PROTECT 1 
#ifdef _GLIBCXX_DEBUG 
#ifdef CRASH 
#undef PROTECT 
#define PROTECT 0 
#warning will crash 
#endif /* CRASH */ 
#endif /* _GLIBCXX_DEBUG */ 
 
class MapTask 
: 
  public ACE_Task_Base 
{ 
  public: 
    MapTask( 
      unsigned long cnt, 
      unsigned long threadCnt 
    ) 
    : 
      m_barrier(threadCnt+1), 
      m_id(0), 
      m_failed(0), 
      m_cnt(cnt), 
      m_threadCnt(threadCnt) 
    { 
      for(cnt = 0; cnt < m_cnt; ++cnt) 
      { 
        m_map[cnt] = 0; 
      } 
       
      this->activate( 
        THR_NEW_LWP|THR_JOINABLE|THR_INHERIT_SCHED, 
        m_threadCnt 
      ); 
    } 
   
    ~MapTask() 
    { 
    } 
   
    virtual int init (int argc, char *argv[]) 
    { 
      m_barrier.wait(); 
      return 0; 
    } 
     
    virtual int fini (void) 
    { 
      this->wait(); 
      return 0; 
    } 
     
    unsigned failed ( ) 
    { 
      return m_failed.value(); 
    } 
     
    virtual int svc (void) 
    { 
      long id = m_id++;       
       
      m_barrier.wait(); 
 
      try 
      { 
        for(int cnt = 0; cnt < m_cnt; ++cnt) 
        { 
          if(id % 2) 
          { 
            WriteGuard guard(m_mutex); 
            m_map[cnt] += 1; 
          } 
           
          std::map<int,int>::const_iterator iter = m_map.end(); 
          { 
            ReadGuard guard(m_mutex); 
            iter = m_map.find(cnt); 
          } 
           
          if(iter == m_map.end()) 
          { 
            ++m_failed; 
          } 
          else 
          { 
            unsigned long value = 0; 
            do 
            { 
              value += iter->second; 
              { 
                // we have to guard the iterator movement 
                // in the debug builds due to _GLIBCXX_DEBUG 
#if PROTECT 
                WriteGuard guard(m_mutex); 
#endif /* PROTECT */ 
                ++iter; 
              } 
            }while(iter != m_map.end()); 
          } 
          ACE_OS::sleep(ACE_Time_Value(0,10)); 
        } 
      } 
      catch(...) 
      { 
        return -1; 
      } 
 
      return 0; 
    } 
         
  private: 
    typedef ACE_Read_Guard < ACE_RW_Thread_Mutex >   ReadGuard; 
    typedef ACE_Write_Guard < ACE_RW_Thread_Mutex >  WriteGuard; 
     
    ACE_Thread_Barrier                                 m_barrier; 
    ACE_RW_Thread_Mutex                                m_mutex; 
    ACE_Atomic_Op <ACE_Thread_Mutex, unsigned long>    m_id; 
    ACE_Atomic_Op <ACE_Thread_Mutex, unsigned long>    m_failed; 
    std::map<int,int>                                  m_map; 
    unsigned long                                      m_cnt; 
    unsigned long                                      m_threadCnt; 
}; 
 
 
int main () 
{ 
  unsigned int numThreads = 200; 
  unsigned int numIterations = 100; 
   
  // create threads 
  MapTask task(numIterations, numThreads); 
  ACE_OS::sleep(1); 
   
  // run threads 
  task.init(0, 0); 
  // wait for completion 
  task.fini(); 
   
  return 0; 
} /* end of main */ 
 
------------------------------------- cut -----------------------------------

-- 
           Summary: Crash in std::map when using _GLIBCXX_DEBUG with
                    multithreading
           Product: gcc
           Version: 3.4.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libstdc++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: lothar at xcerla dot com
                CC: gcc-bugs at gcc dot gnu dot org


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


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