2011-12-02 6 views
16

मुझे एक बहुत ही खराब मेमोरी लीक मिली है जिसे मैं ठीक करने की कोशिश कर रहा हूं, लेकिन किसी भी तरह से मैं इस जोर से ट्रिगर किए बिना ऑब्जेक्ट्स को हटाने में सक्षम नहीं हूं।डीबग सम्मिलन विफल ... _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

मैंने Google के माध्यम से एक समाधान की खोज की है और इस त्रुटि के बारे में stackoverflow पर प्रश्न पढ़े हैं लेकिन मुझे अभी भी जवाब नहीं मिला!

करने के कारणों में अपना शोध के अनुसार इस त्रुटि प्राप्त करने के लिए:
1. हटाने वस्तुओं एक से अधिक
2. छाया नकल
3. बनाने और वस्तुओं है कि एक बाहरी dll से भरी हुई हैं, उन्हें हटाकर
4. बनाने सूचक

लेकिन भंडारण के बिना वस्तुओं:
1. मैं कोड की जाँच की और डबल विलोपन
2. मैं एक प्रति निर्माता का उपयोग वस्तुओं
कॉपी करने के लिए खोजने के लिए सक्षम नहीं था3. त्रुटि रिलेट क्लास एक अलग lib के लिए (एमएस विजुअल स्टूडियो के साथ) बना रहे हैं लेकिन एक डीएल के लिए नहीं। और इस त्रुटि से संबंधित सभी वर्ग एक ही lib में स्थित हैं।
4. मैं कोड की जाँच की और ऐसा लगता है कि समस्या

यह बहुत अच्छा है, तो किसी को नीचे दिए गए कोड में गलती का पता करने में सक्षम है किया जाएगा नहीं है की तरह है, और मैं हर संकेत है कि मुझे के समाधान के लिए अंक की सराहना मुसीबत।

संपादित करें:
मैं MessageSystem की sendThreadMain (नीचे कोड देखें) में एक ही हटाने से समस्या उल्लेख करना भूल गया। अगर मैं वहां संदेश हटा देता हूं तो यह कोड में कहीं और अप्रत्याशित त्रुटियों का कारण बनता है। शायद गलत डेटा ट्रांसमिशन हो सकता है ... लेकिन मुझे वास्तव में पता नहीं है।
यह कोड विंडोज और लिनक्स पर चलाया गया है!

यहाँ संबंधित कोड के कुछ हिस्सों त्रुटि हैं:

संदेश

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::~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

आप 'प्रसारण' फ़ंक्शन की तुलना में किसी अन्य स्थान पर कतार में संदेश नहीं जोड़ते हैं? –

+0

अच्छी खबर और बुरी खबर है। अच्छी खबर यह है कि यह निश्चित रूप से स्मृति रिसाव के कारण नहीं होता है। –

+0

मुझे यकीन नहीं है कि यह समस्या है लेकिन आपके पास क्लास संदेश में आभासी विनाशक होना चाहिए। –

उत्तर

3

आज मैंने इसे अपने आप से बाहर निकाला। यह प्रश्न में उल्लिखित 4 संभावनाओं में से # 1 था।

  1. हटाने एक बार फिर और अधिक वस्तुओं

यहाँ MessageQueue में मेरे समाधान है (ठीक उसी वस्तु के लिए कई संकेत दिए गए सहेजकर):

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

मुझे यह भी लगता है कि इसका कतार पर कोई प्रभाव नहीं होना चाहिए, लेकिन मैं वैसे भी कोशिश करूंगा। लेकिन यह एक और समस्या प्रतीत होती है क्योंकि संदेशों को हटाने से उन्हें कतार से हटाने के बाद काम नहीं होता है (संदेश सिस्टम के अंत में लूप देखते समय) – 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)); 

और यह चला गया है।

संबंधित मुद्दे