2012-05-23 3 views
0

Я пытаюсь создать многопоточное графическое сетевое приложение с использованием boost, raknet и irrlicht. Я использую один поток, который получает сообщения и другой поток для обработки сообщений и всей графической работы.Доступ к месту нарушения прав доступа. Куча коррупции. Boost thread

это экран ошибки я получаю

первого шанса исключение в 0x77183c8d в NetSystemForVideogamesServerTester.exe: 0xC0000005: Нарушение прав доступа чтения местоположение 0x0d99d472

это выходная информация окно

HEAP [NetSystemForVideogamesServerTester.exe]: HEAP: свободный блок кучи da58d10 изменен на da58fe0 после освобождения Windows вызвала точку останова в NetSystemForVideogamesServerTester.exe.

Это может быть из-за коррупции кучи, что указывает на ошибку в NetSystemForVideogamesServerTester.exe или любой из библиотек DLL он загружены.

Это может быть связано с тем, что пользователь нажал клавишу F12, в то время как NetSystemForVideogamesServerTester.exe имеет фокус.

Выходное окно может содержать больше диагностической информации.

это когда я запускаю нить

void receive() 
    {  
     boost::thread(&IConnectionInstance::receiveInThread, this); 
    } 

мьютекса декларация

boost::mutex mMessagesReceived; 

это код из получающего потока

void RakNetConnectionInstance::receiveInThread() 
{ 
    Packet* packet; 
    IMessage* message = NULL; 
    long time = 0; 

    while (true) 
    { 
     message = NULL; 
     packet = aPeer->Receive(); 

     while (packet) 
     {   
      RakNet::BitStream* dataStream = new RakNet::BitStream(packet->data, packet->length, false); 
      dataStream->IgnoreBits(sizeof(unsigned char)*8);  

      switch (packet->data[0]) 
      {    

      case ID_TIMESTAMP: 
       { 
        dataStream->Read(time); 
        int countMessagesAggregated = 0; 
        dataStream->Read(countMessagesAggregated); 
        unsigned char messageType = char(); 

        IBitStream* bitStream = new RakNetBitStream(dataStream); 

        while(countMessagesAggregated > 0) 
        {      
         dataStream->Read(messageType); 

         switch ((EMESSAGE_TYPE)messageType) 
         { 
         case EACTOR_CONTENT_MESSAGE:        
          message = new CActorContentMessage(aUserDataFactory);       
          break; 
         case EWORLD_CONTENT_MESSAGE:        
          message = new CWorldClientContentMessage(aUserDataFactory);       
          break;             
         case EUSER_COMMAND_MESSAGE: 
          message = new CUserCommandMessage(aEventFactory);       
          break; 
         case EPREDICTION_MESSAGE: 
          message = new CPredictionMessage(aUserDataFactory);       
          break; 
         case EPREDICTION_RESPONSE_MESSAGE: 
          message = new CPredictionResponseMessage(aUserDataFactory);      
          break; 
         } 

         countMessagesAggregated --; 

         if (messageType >= EUSER_MESSAGE && aCustomReceiver) 
         { 
          aCustomReceiver->receiveCustomMessages(); 
         } 

         if (message) 
         { 
          message->readFromBitStream(bitStream); 
          message->setTimeMS(time); 
          message->setIPAddress(packet->systemAddress.ToString(false)); 
          message->setPort(packet->systemAddress.port); 

          mMessagesReceived.lock(); 
          aMessagesReceivedQueue.push(message); 
          printf("adicionando mensaje a cola en lock\n"); 
          mMessagesReceived.unlock(); 
          message = NULL; 
         } 
        }          
       } 
       break; 
      } 

      if (message) 
      { 
       message->setTimeMS(time); 
       message->setIPAddress(packet->systemAddress.ToString(false)); 
       message->setPort(packet->systemAddress.port); 

       mMessagesReceived.lock(); 
       aMessagesReceivedQueue.push(message); 
       mMessagesReceived.unlock(); 
      } 

      aPeer->DeallocatePacket(packet); 
      packet = aPeer->Receive();    
     } 
     if (RakNet::GetTimeMS() - aBeginTimeSearchServersActives > aWaitTimeServersActives && !aTimeOut) 
     { 
      boost::mutex::scoped_lock lock(mTimeOut); 
      aTimeOut = true; 
     } 
    } 
} 

здесь я посещаю сообщение от очередь в профильной нити

void CMessageManager::attendMessages() 
{ 
    std::queue<IMessage*> messages = aConnectionInstance->getMessagesReceivedFromQueue(); 

    while(!messages.empty()) 
    { 
     notifyMessage(messages.back()); 
     aConnectionInstance->popMessageReceivedFromQueue();  
     messages.pop();    
    }  
} 

здесь я получить доступ к очереди сообщений

std::queue<IMessage*> RakNetConnectionInstance::getMessagesReceivedFromQueue() 
{  
    boost::mutex::scoped_lock lock(mMessagesReceived); 
    std::queue<IMessage*> messages; 
    messages = aMessagesReceivedQueue; 
    return messages; 
} 

и, наконец, здесь я удалить сообщение из очереди

void RakNetConnectionInstance::popMessageReceivedFromQueue() 
{ 
    boost::mutex::scoped_lock lock(mMessagesReceived); 
    if (!aMessagesReceivedQueue.empty()) 
    {  
     aMessagesReceivedQueue.pop();    
    } 
} 

Я новичок в C++ и многопоточность, пожалуйста, помогите мне, Что я делаю неправильно? Спасибо заранее.

+1

То есть много кода, чтобы попросить кого-нибудь прочитать более. Вы пытались запустить код в отладчике? Вы должны иметь возможность настроить отладчик, чтобы сообщить вам, где это исключение было нарушено, что может облегчить задачу идентификации проблемы. – obmarg

ответ

0

Вы не удаляете сообщения из исходной очереди, вы просто копируете указатели в новую очередь. Так происходит:

  1. Получаете сообщение. Указатель на него переходит в очередь.

  2. Вы копируете очередь, обрабатываете сообщение и удаляете его.

  3. Получаемое другое сообщение.

  4. Вы копируете очередь. Тем не менее, он все еще содержит указатель на первое сообщение.

  5. Вы получаете доступ к указателю на первое сообщение, которое вы удалили.

Этот код нарушается, поскольку он копирует очередь оставляя оригинал без изменений:

std::queue<IMessage*> RakNetConnectionInstance::getMessagesReceivedFromQueue() 
{  
    boost::mutex::scoped_lock lock(mMessagesReceived); 
    std::queue<IMessage*> messages; 
    messages = aMessagesReceivedQueue; 
    return messages; 
} 
+0

спасибо за ответ, но я удаляю сообщение из обеих очередей. Я делаю это в функции attendMessages() из блока кода 4. Любые другие идеи? – Liz

Смежные вопросы