2011-12-02 11 views
16

私は本当に悪いメモリリークを抱えていますが、私は修正しようとしていますが、何とかこのアサーションをトリガーしないでオブジェクトを削除できません。デバッグアサーションに失敗しました... _BLOCK_TYPE_IS_VALID(pHead-> nBlockUse)

私はGoogle経由で解決策を探していますが、このエラーについてのstackoverflowに関する質問を読んでいますが、まだ回答を見つけることができませんでした。

考えられる理由は、私の研究によると、このエラーを取得する:
1.削除は、オブジェクトより1つの
2.シャドウコピー
3.作成し、外部DLLからロードされたオブジェクトを削除
4.作成後、ポインタ

しかし保存せずにオブジェクト:
1.私は、コードをチェックし、私はオブジェクト
をコピーするにはコピーコンストラクタを使用し
2.二重欠失を見つけることができませんでした3. Error relatetクラスは、(MS Visual Studioを使用して)別のライブラリにビルドされていますが、DLLにはありません。このエラーに関連するすべてのクラスは同じlibにあります。
4.私は、コードをチェックし、それが問題

ないように、誰もが次のコードでミスを発見することができる場合それは素晴らしいことだと思われる、と私はの溶液に私を指すすべてのヒントに感謝問題。

編集:
MessageSystemのsendThreadMain(下記のコードを参照)で同じ削除の問題について言及し忘れました。そこにメッセージを削除すると、コード内のどこかで予期しないエラーが発生します。間違ったデータ送信があるかもしれません...しかし、私は本当に知っていません。
このコードはWindowsおよびLinux上で実行されます。ここで

は、コードのエラーに関連する部分です:

メッセージ

class Message 
{ 
public: 
    Message (char type, unsigned char id, unsigned short size) 
    { 
     mType = type; 
     mId = id; 
     mSize= size; 
    } 

    Message(const Message &o) 
    { 
     mType = o.mType; 
     mId = o.mId; 
     mSize = o.mSize; 
    } 

    char getType() const {return mType;}; 
    unsigned char getId() const {return mId;}; 
    unsigned short getSize() const {return mSize;}; 

protected: 
    char mType; 
    unsigned char mId; 
    unsigned short mSize; 
}; 


class JoinMessage : public Message 
{ 
public: 
    JoinMessage() : Message ('j', 0, sizeof (JoinMessage)) 
    { 
     team = TEAM_SPECTATOR; 
    } 
    JoinMessage (unsigned char id) : Message ('j', id, sizeof (JoinMessage)){} 
    JoinMessage (const JoinMessage &o) : Message (o) 
    { 
     team = o.team; 
     setName(o.getName()); 
    } 


    void setName(std::string newName) 
    { 
     if (newName.length() > MAX_PLAYER_NAME_LENGHT) 
      newName = newName.substr(0, MAX_PLAYER_NAME_LENGHT); 

     memset(name, 0, MAX_PLAYER_NAME_LENGHT); 
     for(unsigned int i = 0; i < newName.length(); i++) 
      name[i] = newName[i]; 
    } 

    std::string getName() const 
    { 
     std::string stringToReturn; 

     for(unsigned int i = 0; i < MAX_PLAYER_NAME_LENGHT; i++) 
     { 
      if (name[i]) 
       stringToReturn.push_back(name[i]); 
      else 
       break; 
     } 

     return stringToReturn; 
    } 

    TeamIdentifier team; 

private: 
    unsigned char name[MAX_PLAYER_NAME_LENGHT]; 
}; 

// there are a lot other messages 

メッセージキュー

MessageQueue::~MessageQueue() 
{ 
    boost::mutex::scoped_lock lock (queueMutex); 

    while(messageQueue.size() > 0) 
    { 
     // the crash is non-reproducible 
     // works 90% of the time 
     delete messageQueue.front(); // <- Debug Assertion Failed … _BLOCK_TYPE_IS_VALID 
     messageQueue.pop_front(); 
    } 

} 

void MessageQueue::enqueMessage (Message* message) 
{ 
    { 
     boost::mutex::scoped_lock lock (queueMutex); 
     messageQueue.push_back(message); 
    } 
} 

Message* MessageQueue::dequeMessage() 
{ 
    boost::mutex::scoped_lock lock (queueMutex); 
    if (messageQueue.size() == 0) 
     return nullptr; 

    Message* message = messageQueue.front(); 
    messageQueue.pop_front(); 

    return message; 
} 

MessageSystem

template <class MessageType> 
void broadcast (MessageType &message) 
{ 
    MessageType *internMessage = new MessageType(message); 

    boost::mutex::scoped_lock lock (mRecipientMapMutex); 
    std::map <boost::asio::ip::udp::endpoint, MessageQueue *>::iterator it; 

    for (it = mRecipientMap.begin(); 
     it != mRecipientMap.end(); 
     it++) 
    { 
     it->second->enqueMessage(internMessage); 

    } 
} 


template <class MessageType> 
void post (MessageType &message, boost::asio::ip::udp::endpoint &recipient) 
{ 
    MessageType *internMessage = new MessageType(message); 

    std::map <boost::asio::ip::udp::endpoint, MessageQueue* >::iterator it; 
    MessageQueue *messageQueue = NULL; 
    { 
     boost::mutex::scoped_lock lock (mRecipientMapMutex); 
     it = mRecipientMap.find (recipient); 
     if (it != mRecipientMap.end()) 
      messageQueue = it->second; 

     if(messageQueue) 
      messageQueue->enqueMessage (internMessage); 
    } 

} 


void MessageSystem::sendThreadMain() 
{ 
    // copy endpoints to vecotr so it can be 
    // deleted from map while iterating 
    std::vector<udp::endpoint> endpoints; 
    { 
     boost::mutex::scoped_lock lock (mRecipientMapMutex); 
     std::map <udp::endpoint, MessageQueue *>::iterator mapIt = mRecipientMap.begin(); 
     while (mapIt != mRecipientMap.end()) 
     { 
      endpoints.push_back(mapIt->first); 
      mapIt++; 
     } 
    } 

    std::vector<udp::endpoint>::iterator endpointIt = endpoints.begin(); 
     while (endpointIt != endpoints.end()) 
     { 
      char sendBuffer[PACKET_SIZE]; 
      int sendBufferPosition = 0; 
      { 
       boost::mutex::scoped_lock lock (mRecipientMapMutex); 

       MessageQueue *messageQueue = mRecipientMap[*endpointIt]; 
       if (messageQueue == nullptr) 
       { 
        mRecipientMap.erase(*endpointIt); 
        endpointIt++; 
        continue; 
       } 

       while (Message *message = messageQueue->dequeMessage()) 
       { 
        if (sendBufferPosition + message->getSize() > PACKET_SIZE) 
        { 
         // put message back and send it later 
         messageQueue->enqueMessage (message); 
         break; 
        } 

        // copy message into buffer 
        std::memcpy (
         &sendBuffer [sendBufferPosition], message, message->getSize()); 

        sendBufferPosition += message->getSize(); 
        // deleting this message causes a crash if 2 or more 
        // recipients are registered within MessageSystem 
        //delete message; <- RANDOM CRASH elsewhere in the program 
       } 
      } 
    .... // more code down here that seems not related to the error 
+0

'broadcast'以外の場所でメッセージをキューに追加しないでください。 –

+0

良いニュースと悪いニュースがあります。良いニュースは、これが最も確実にメモリリークが原因ではないということです。 –

+0

これが問題なのかどうかはわかりませんが、Messageクラスに仮想デストラクタが必要です。 –

答えて

3

今日私はそれを自分で考え出しました。それは質問で言及された4つの可能性のうちの#1でした。オブジェクトに多くを削除

  1. そして、ここで

(まったく同じオブジェクトに複数のポインタを保存して)一度は、メッセージキューの私のソリューションです:

template <class MessageType> 
void broadcast (MessageType &message) 
{ 
    // I was creating 1 new Message right here but I need 1 new Message 
    // in EVERY MessageQueue so i moved the next line ... 
    // MessageType *internMessage = new MessageType(message); 

    boost::mutex::scoped_lock lock (mRecipientMapMutex); 
    std::map <boost::asio::ip::udp::endpoint, MessageQueue *>::iterator it; 

    for (it = mRecipientMap.begin(); 
     it != mRecipientMap.end(); 
     it++) 
    { 
     // ... down here. Now every queue contains its own copy of the Message 
     MessageType *internMessage = new MessageType(message); 
     it->second->enqueMessage(internMessage); 
    } 
} 
1

これは、単純なプロのかもしれません間違った順序の傷。あなたはやっている:

while(messageQueue.size() > 0) 
{ 
    delete messageQueue.front(); 
    messageQueue.pop_front(); 
} 

多分トリック行うだろう、前にそれをポップした後、メッセージを削除、代わりに:とにかく

while(messageQueue.size() > 0) 
{ 
    Message* pFront = messageQueue.front(); 
    messageQueue.pop_front(); 
    delete pFront; 
} 

を、私は削除するので、このソリューションには全く自信がないですpFrontが指すオブジェクトは、ポインタ自体を格納するキュー自体には影響を与えません。しかし、あなたは試すことができます。

+1

キューには影響しないはずですが、とにかく試してみます。しかし、メッセージを削除することはQueueから削除しても機能しないので、別の問題であるようです(MessageSystemの最後のwhileループを参照) – cwin

1

まあ、私は 、同様の問題に直面しました次のコード

Message* message = messageQueue.front(); 
messageQueue.pop_front(); 

return message; 

私と一緒に、エラーが発生したコードされた:

Point *p = q.LookFor(&q, &pts[5], &Dist); 
cout ... 
delete p; 

それはとても私はそれを置き換える関数は、実行時に作成ポインタを削除しているようですので、あなたが「もう一度」、それを削除するには

を許可されていません

Point p = *(q.LookFor(&q, &pts[5], &Dist)); 

となりました。

関連する問題