Я делаю отладку для многопоточной программы C ++ (pthread) в Linux.
Хорошо работает, когда номер резьбы мал, например 1, 2,3.
Когда номер потока увеличивается, я получаю SIGSEGV (ошибка сегментации, сигнал UNIX 11).
Но ошибка иногда появляется, а иногда исчезает, когда я увеличиваю число потоков выше 4.
Я использовал Valgrind, я получил
== 29655 == Процесс завершается с действием по умолчанию для сигнала 11 (SIGSEGV)
== 29655 == Доступ не в сопоставленной области по адресу 0xFFFFFFFFFFFFFFF8
== 29655 == в 0x3AEB69CA3E: std :: string :: assign (std :: string const &) (в /usr/lib64/libstdc++.so.6.0.8)
== 29655 == по 0x42A93C: bufferType :: getSenderID (std :: string &) const (boundedBuffer.hpp: 29)
Кажется, мой код пытался прочитать память, которая не выделена.
Но я не могу найти никаких ошибок в функции getSenderID (). Он возвращает только строку данных члена в классе bufferType. Это было инициализировано.
Я использовал GDB и DDD (GDB GUI), чтобы найти ошибку, которая также указывает на это, но ошибка иногда исчезает, так что в GDB я не могу захватить ее с точкой останова.
Более того, я также распечатываю значения функции, на которую указывает valgrind, но это бесполезно, потому что несколько потоков выводят результаты в разных порядках, и они чередуются друг с другом. Каждый раз, когда я запускаю код, вывод на печать отличается.
Параметр bufferType находится на карте, карта может иметь несколько записей. Каждая запись может быть записана одним потоком и прочитана другим потоком одновременно. Я использовал блокировку чтения / записи pthread для блокировки 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; }
} ;
Из кода видно, что я пытался использовать блокировку чтения / записи для обеспечения инварианта.
Каждая запись в карте имеет буфер, подобный приведенному выше. Теперь у меня тупик.