gpt4 book ai didi

c++ - 调试断言失败…_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

转载 作者:IT老高 更新时间:2023-10-28 22:22:15 24 4
gpt4 key购买 nike

我正在尝试修复一个非常严重的内存泄漏,但不知何故我无法在不触发此断言的情况下删除对象。

我已通过 Google 搜索了解决方案,并已阅读有关此错误的 Stackoverflow 上的问题,但我仍然无法找到答案!

根据我的研究,出现此错误的可能原因:
1. 删除多个对象
2.影子复制
3.创建和删除从外部dll加载的对象
4. 创建对象而不存储指针

但是:
1.我检查了代码,没有找到双重删除
2.我使用拷贝构造函数来拷贝Objects
3. 错误相关类(使用 MS Visual Studio)构建到单独的库而不是 dll。并且与此错误相关的所有类都位于同一个库中。
4.我检查了代码,似乎不是问题

如果有人能够在下面的代码中发现错误,那就太好了,我很感激每一个提示我解决问题的方法。

编辑:
我忘了在 MessageSystem 的 sendThreadMain 中提到同样的删除问题(见下面的代码)。如果我在那里删除消息,它会导致代码中其他地方出现意外错误。可能只是数据传输错误……但我真的不知道。
此代码在 Windows 和 Linux 上运行!

以下是代码中与错误相关的部分:

留言

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()
{
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;
}

消息系统

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

最佳答案

今天我自己想通了。这是问题中提到的 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);
}
}

关于c++ - 调试断言失败…_BLOCK_TYPE_IS_VALID(pHead->nBlockUse),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8354578/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com