jjzjj

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

coder 2023-06-02 原文

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

我已通过 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/

有关c++ - 调试断言失败…_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  5. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  6. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  7. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  8. ruby-on-rails - 无法让 rspec、spork 和调试器正常运行 - 2

    GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'

  9. ruby - 在匿名 block 中产生 - 2

    我没有理解以下行为(另请参阅inthisSOthread):defdef_testputs'def_test.in'yieldifblock_given?puts'def_test.out'enddef_testdoputs'def_testok'endblock_test=procdo|&block|puts'block_test.in'block.callifblockputs'block_test.out'endblock_test.calldoputs'block_test'endproc_test=procdoputs'proc_test.in'yieldifblock_gi

  10. ruby - JetBrains RubyMine 3.2.4 调试器不工作 - 2

    使用Ruby1.9.2运行IDE提示说需要gemruby​​-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall

随机推荐