C++ 调试断言失败……_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8354578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Debug Assertion Failed … _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
提问by cwin
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!
我已经通过 Google 搜索了解决方案,并阅读了有关此错误的 stackoverflow 上的问题,但我仍然无法找到答案!
Possible reasons to get this Error according to my research:
1. deleting objects more then one
2. shadow copying
3. creating and deleting Objects that are loaded from an external dll
4. creating objects without storing the pointer
根据我的研究,出现此错误的可能原因:
1. 删除多个对象
2. 影子复制
3. 创建和删除从外部 dll 加载的
对象 4. 创建对象而不存储指针
BUT:
1. I checked the code and was not able to find double deletion
2. I use a copy constructor to copy Objects
3. The Error relatet classes are build (with MS Visual Studio) to a seperate lib but not to a dll. AND all the classes that are related to this error are located in the same lib.
4. I checked the code and it seems like that's not the problem
但是:
1. 我检查了代码并且无法找到双重删除
2. 我使用复制构造函数来复制对象
3. 错误相关类构建(使用 MS Visual Studio)到一个单独的库而不是一个 dll。并且与此错误相关的所有类都位于同一个库中。
4.我检查了代码,似乎这不是问题
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). 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!
编辑:
我忘了在 MessageSystem 的 sendThreadMain 中提到同样的删除问题(见下面的代码)。如果我在那里删除消息,它会导致代码中其他地方出现意外错误。可能只是错误的数据传输......但我真的不知道。
此代码可在 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()
{
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
采纳答案by cwin
Today I figured it out on my own. It was #1 of the 4 possibilities mentioned in the Question.
今天我自己弄明白了。它是问题中提到的 4 种可能性中的第 1 种。
- deleting objects more then once (by saving multiple pointers to the exact same object)
- 多次删除对象(通过保存指向完全相同对象的多个指针)
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);
}
}
回答by Ahmed U3
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.
它不见了。
回答by Gorpik
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 pFrontshould have no effect on the queue itself, which just stores pointers. But you can try.
无论如何,我对这个解决方案一点信心都没有,因为删除指向的对象pFront应该对队列本身没有影响,队列本身只存储指针。不过你可以试试。

