2011-12-02 5 views
16

Tengo una muy mala pérdida de memoria que estoy tratando de corregir, pero de alguna manera no puedo eliminar Objetos sin desencadenar esta afirmación.Confirmación de depuración Falló ... _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

He buscado una solución a través de Google y he leído las Preguntas sobre stackoverflow sobre este Error pero todavía no he podido encontrar la respuesta.

razones posibles para conseguir este error de acuerdo a mi investigación: Objetos
1. borrar más de un
2. copia sombra
3. Creación y eliminación de objetos que se cargan desde una DLL externa
4. Crear objetos sin almacenar el puntero

PERO:
1. he comprobado el código y no era capaz de encontrar deleción doble
2. utilizo un constructor de copia para copiar objetos
3. Las clases de relaate de error se compilan (con MS Visual Studio) en una lib separada, pero no en una dll. Y todas las clases que están relacionadas con este error se encuentran en la misma lib.
4. he comprobado el código y parece que ese no es el problema

Sería muy bueno si alguien es capaz de detectar el error en el código de abajo, y aprecio cada pista que me apunta a la solución del problema.

EDIT:
Se me olvidó mencionar el mismo problema de eliminación en sendThreadMain de MessageSystem (ver código a continuación). Si elimino el mensaje allí, causa errores inesperados en otro lugar en el código. Podría ser una transmisión de datos errónea ... pero realmente no lo sé.
¡Este código se ejecuta en Windows y Linux!

Aquí están los errores relacionados con partes del código:

mensaje

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

No agrega mensajes a la cola en ningún otro lugar que la función 'broadcast'? –

+0

Hay buenas y malas noticias. La buena noticia es que esto definitivamente no es causado por una pérdida de memoria. –

+0

No estoy seguro de si este es el problema, pero debería tener un destructor virtual en la clase Mensaje. –

Respuesta

3

Hoy me di cuenta por mi cuenta. Fue el # 1 de las 4 posibilidades mencionadas en la Pregunta.

  1. eliminación de objetos más de una vez (por el ahorro de varios punteros al mismo objeto exacto)

Aquí está mi solución en 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

Podría ser un profesional sencilla blem de orden equivocado. Que está haciendo:

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

borrar Tal vez el mensaje después de hacer estallar, en lugar de antes, que hacer el truco:

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

De todos modos, no estoy seguro de nada en esta solución, ya que la supresión de la el objeto apuntado por pFront no debería tener ningún efecto en la cola, que solo almacena punteros. Pero puedes intentar.

+1

También creo que no debería tener ningún efecto en la cola, pero intentaré eso de todos modos. Pero parece ser otro problema ya que la eliminación de mensajes no funciona después de eliminarlos de la cola (ver while loop al final de MessageSystem) – cwin

1

Bueno, me enfrentaba a problemas similares, el siguiente código

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

return message; 

The código que produce el error conmigo fue:

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

Parece que la función de borrar el puntero se crea en el tiempo de ejecución, por lo que no está permitido para eliminarlo "nuevo"

así que lo reemplazó con

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

y se ha ido.

Cuestiones relacionadas