Как найти ошибку (segmentation fault) в многопоточной программе C++ (pthread) на linux?

Я делаю отладку для (pthread) многопоточной программы C++ на Linux.

Она работает хорошо, когда число потоков невелико, например 1, 2, 3.

Когда число потоков увеличивается, я получаю SIGSEGV (segmentation fault, UNIX signal 11).

Но ошибка иногда появляется, а иногда исчезает, когда я увеличиваю число потоков выше 4.

Я использовал valgrind, я получил

==29655== Процесс завершается с действием по умолчанию сигнала 11 (SIGSEGV)

==29655== Access not within mapped region at address 0xFFFFFFFFFFFFFFF8

==29655== at 0x3AEB69CA3E: std::string::assign(std::string const&) (in /usr/lib64/libstdc++.so.6 .0.8)

==29655== by 0x42A93C: bufferType::getSenderID(std::string&) const (boundedBuffer.hpp:29)

Похоже, что мой код пытался прочитать память, которая не выделена. Но я не могу найти никаких ошибок в функции getSenderID(). Она возвращает только строку данных члена класса bufferType. Он был инициализирован.

Я использовал GDB и DDD (GDB GUI), чтобы найти ошибку, которая также указывает на это, но ошибка иногда исчезает, так что в GDB я не могу поймать ее с помощью точки останова.

Более того, я также вывел значения функции, на которую указывает valgrind, но это не помогло, потому что несколько потоков выводят результаты в разном порядке и они чередуются друг с другом. Каждый раз, когда я запускаю код, вывод на печать отличается.

БуферТип находится в карте, карта может иметь несколько записей. Каждая запись может быть записана одним потоком и прочитана другим потоком в одно и то же время. Я использовал pthread read/write lock для блокировки pthread_rwlock_t. Теперь нет SIGSEGV, но программа останавливается в какой-то момент без прогресса. Я думаю, что это тупик. Но, одна запись карты может быть записана только одним потоком в один момент времени, почему же тогда тупик?

Не могли бы вы порекомендовать мне какие-нибудь методы для фиксации ошибки, чтобы я мог найти ее независимо от того, сколько потоков я использую для выполнения кода.

спасибо

Код boundedBuffer.hpp выглядит следующим образом:

 class bufferType
 {
 private:

    string senderID;// who write the buffer

    string recvID; // who should read the buffer

    string arcID; // which arc is updated

    double price; // write node's price 

    double arcValue; // this arc flow value 

    bool   updateFlag ;

    double arcCost;


    int  arcFlowUpBound; 

    //boost::mutex  senderIDMutex; 

    //pthread_mutex_t  senderIDMutex; 

    pthread_rwlock_t       senderIDrwlock;

    pthread_rwlock_t    setUpdateFlaglock;

  public: 
   //typedef boost::mutex::scoped_lock lock;  // synchronous read / write 

   bufferType(){}

   void   getPrice(double& myPrice ) const {myPrice = price;}

   void   getArcValue(double& myArcValue ) const {myArcValue = arcValue;}

   void   setPrice(double& myPrice){price = myPrice;}

   void   setArcValue(double& myValue ){arcValue = myValue;}

   void   readBuffer(double& myPrice, double& myArcValue );

   void   writeBuffer(double& myPrice, double& myArcValue );

   void   getSenderID(string& myID) 

   {
       //boost::mutex::scoped_lock lock(senderIDMutex);
      //pthread_rwlock_rdlock(&senderIDrwlock); 
      cout << "senderID is " << senderID << endl ; 
      myID = senderID;
      //pthread_rwlock_unlock(&senderIDrwlock);
   }
//void   setSenderID(string& myID){ senderID = myID ;}

    void   setSenderID(string& myID)

    { 
        pthread_rwlock_wrlock(&senderIDrwlock); 

            senderID = myID ;

            pthread_rwlock_unlock(&senderIDrwlock);
    }

    void   getRecvID(string& myID) const {myID = recvID;}

    void   setRecvID(string& myID){ recvID = myID ;}

    void   getArcID(string& myID) const {myID  = arcID ;}

    void   setArcID(string& myID){arcID = myID ;}

    void   getUpdateFlag(bool& myFlag)
    {
            myFlag = updateFlag ; 

        if (updateFlag)

           updateFlag  = false; 
    }

//void   setUpdateFlag(bool myFlag){ updateFlag = myFlag ;}

    void   setUpdateFlag(bool myFlag)
    { 
        pthread_rwlock_wrlock(&setUpdateFlaglock);

        updateFlag = myFlag ;

         pthread_rwlock_unlock(&setUpdateFlaglock);

    }

   void   getArcCost(double& myc) const {myc = arcCost; }

   void   setArcCost(double& myc){ arcCost = myc ;}

   void   setArcFlowUpBound(int& myu){ arcFlowUpBound = myu ;}

   int    getArcFlowUpBound(){ return arcFlowUpBound ;}

   //double getLastPrice() const {return price; }

   } ;

Из кода видно, что я пытался использовать блокировку чтения/записи для обеспечения неизменности. Каждая запись в map имеет буфер, как показано выше. Теперь я получил тупик.

5
задан user1002288 29 January 2012 в 17:47
поделиться