[英]Debug Assertion Failed … _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
I have got a really bad memory leak I am trying to fix, but somehow i am not able to delete Objects without triggering this assertation. 我有一个非常糟糕的内存泄漏,我试图修复,但不知何故,我不能删除对象而不触发此断言。
I have searched for a solution via Google and have read the Questions on stackoverflow about this Error but I was still not able to find the answer! 我已经通过谷歌搜索了一个解决方案并已阅读有关此错误的有关stackoverflow的问题,但我仍然无法找到答案!
Possible reasons to get this Error according to my research: 根据我的研究得出此错误的可能原因:
1. deleting objects more then one 1.删除多个对象
2. shadow copying 2.影子复制
3. creating and deleting Objects that are loaded from an external dll 3.创建和删除从外部DLL加载的对象
4. creating objects without storing the pointer 4.在不存储指针的情况下创建对象
BUT: 但:
1. I checked the code and was not able to find double deletion 我检查了代码,但未能找到双重删除
2. I use a copy constructor to copy Objects 2.我使用复制构造函数来复制对象
3. The Error relatet classes are build (with MS Visual Studio) to a seperate lib but not to a dll. 3.错误的关联类是建立(使用MS Visual Studio)到单独的lib而不是dll。 AND all the classes that are related to this error are located in the same lib.
并且与此错误相关的所有类都位于同一个lib中。
4. I checked the code and it seems like that's not the problem 我检查了代码,看起来这不是问题
It would be great if anybody is able to spot the mistake in the code below, and I appreciate every hint that points me to the solution of the problem. 如果有人能够在下面的代码中发现错误,那将是很好的,我感谢每一个指示我解决问题的提示。
EDIT: 编辑:
I forgot to mention the same deleting problem in sendThreadMain of MessageSystem (see code below). 我忘了在MessageSystem的sendThreadMain中提到相同的删除问题(参见下面的代码)。 If i delete the Message there it causes unexpected errors somewhere else in the code.
如果我删除消息,它会在代码中的其他地方导致意外错误。 Might just be wrong data transmission... but i do not really know.
可能只是错误的数据传输......但我真的不知道。
This code is run on Windows and Linux! 此代码在Windows和Linux上运行!
Here are the error related parts of the code: 以下是代码的错误相关部分:
Message 信息
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::~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 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
Today I figured it out on my own. 今天我自己想出来了。 It was #1 of the 4 possibilities mentioned in the Question.
它是问题中提到的4种可能性中的第1种。
Here is my Solution in MessageQueue: 这是我在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);
}
}
Well, I faced similar problem, the following code 好吧,我遇到了类似的问题,下面的代码
Message* message = messageQueue.front ();
messageQueue.pop_front();
return message;
The code that produced error with me was: 与我产生错误的代码是:
Point *p = q.LookFor(&q, &pts[5], &Dist);
cout ...
delete p;
It seems that the function delete the pointer it creates in the runtime, so you're not allowed to delete it "again" 似乎该函数删除了它在运行时创建的指针,因此不允许“再次”删除它
so I replaced it with 所以我换了
Point p = *(q.LookFor(&q, &pts[5], &Dist));
and it's gone. 它已经消失了。
It might be a simple problem of wrong order. 这可能是错误订单的简单问题。 You are doing:
你在做:
while(messageQueue.size() > 0)
{
delete messageQueue.front();
messageQueue.pop_front();
}
Maybe deleting the message after popping it, instead of before, would do the trick: 也许在弹出消息之后删除消息,而不是之前,可以做到这一点:
while(messageQueue.size() > 0)
{
Message* pFront = messageQueue.front();
messageQueue.pop_front();
delete pFront;
}
Anyway, I am not confident at all on this solution, since deleting the object pointed by pFront
should have no effect on the queue itself, which just stores pointers. 无论如何,我对此解决方案一点也不自信,因为删除
pFront
指向的对象应该对队列本身没有影响,队列本身只存储指针。 But you can try. 但你可以试试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.