0

ブースト、raknet、irrlicht を使用して、マルチスレッドのグラフィカル ネットワーク アプリケーションを作成しようとしています。メッセージを受信する 1 つのスレッドと、メッセージとすべてのグラフィック作業を処理する別のスレッドを使用します。

これは私が得ているエラー画面です

NetSystemForVideogamesServerTester.exe の 0x77183c8d での初回例外: 0xC0000005: アクセス違反の読み取り場所 0x0d99d472

これは出力ウィンドウ情報です

HEAP[NetSystemForVideogamesServerTester.exe]: ヒープ:解放された後、da58fe0 で変更されたフリー ヒープ ブロック da58d10 Windows が NetSystemForVideogamesServerTester.exe でブレークポイントをトリガーしました。

これは、ヒープの破損が原因である可能性があります。これは、NetSystemForVideogamesServerTester.exe または読み込まれた DLL のバグを示しています。

これは、NetSystemForVideogamesServerTester.exe にフォーカスがあるときにユーザーが F12 を押したことが原因である可能性もあります。

出力ウィンドウには、より多くの診断情報が表示される場合があります。

これは私がスレッドを立ち上げたときです

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++ とマルチスレッドが初めてです, 助けてください, 何が間違っていますか? 前もって感謝します。

4

1 に答える 1

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;
}
于 2012-05-23T22:53:38.273 に答える