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 pFront
should have no effect on the queue itself, which just stores pointers. But you can try.
无论如何,我对这个解决方案一点信心都没有,因为删除指向的对象pFront
应该对队列本身没有影响,队列本身只存储指针。不过你可以试试。