std :: unordered_map中可能存在的错误

yas*_*101 0 c++ unordered-map segmentation-fault c++11

我试图找到一个段错误背后的罪魁祸首.我的调试器告诉我,错误所在的变量没有数据.每隔10秒,我的C++代码中会运行一个小脚本.它做"垃圾收集"并删除一些可能已经死亡的"会话".为了有效地执行此操作,我使用时间戳 - 上次访问数据的时间.如果数据超过10秒,那就已经死了.有一个keepalive命令在客户端上每4秒触发一次.

为了执行此GC,我遍历std :: unordered_map并从存储为该对中的值的时间中减去自纪元以来的当前时间.如果时间太大,我将它添加到一个std :: vector,它包含要删除的键(是的,我知道它可以被优化以跳过这一步).

我面临的问题是它第一次循环正确.然而,此后,我得到一个段错误,它指向迭代器值大于地图的大小.只需切换回标准的std :: map就可以解决整个问题!

我将附上完成所有这一切的功能.所有代码都可以在http://github.com/yash101/DrawingPad上找到

现在,代码[{sourcedir} /source/Session.cxx]:

void SessionHost::cron()
{
    while(true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(10));
        if(DEBUG)
        {
            std::cout << "Cron has started!" << std::endl;
        }

        while(!locky_thingy.try_lock_for(std::chrono::milliseconds(MUTEX_TIMEOUT)))
        {}

        int timethrough = 0;
        std::vector<std::string> del;
        for(std::map<std::string, long>::iterator ite = timestamp.begin(); ite != timestamp.end(); ++ite)
        {
            timethrough++;
            std::cout << "Time through: " << timethrough << std::endl;
            std::string curkey = ite->first;
            long curval = ite->second;
            std::cout << "Key: " << curkey << std::endl;
            if(DEBUG)
            {
                std::cout << "Checking " << curkey << " with old ts of " << curval << std::endl;
            }

            u_int64_t curtm = std::chrono::duration_cast<std::chrono::milliseconds> (std::chrono::system_clock::now().time_since_epoch()).count();
            if(DEBUG)
            {
                std::cout << "Current time: " << curtm << std::endl;
            }
            if(curtm - curval > SESSION_TIMEOUT)
            {
                if(DEBUG)
                {
                    std::cout << "Deleted session handle: [" << curkey << "]" << std::endl;
                }
                del.push_back(curkey);
            }
            else
            {
                if(DEBUG)
                {
                    std::cout << "Kept back session handle: [" << curkey << "]" << std::endl;
                }
            }

            for(unsigned int i = 0; i < del.size(); i++)
            {
                timestamp.erase(del[i]);
                data.erase(del[i]);
                std::cout << "Erasing: " << del[i] << std::endl;
            }
        }

        locky_thingy.unlock();
    }
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 7

你有:

for(std::map<std::string, long>::iterator ite = timestamp.begin(); 
                                    ite != timestamp.end(); ++ite)
{
    // ...
    for(unsigned int i = 0; i < del.size(); i++)
    {
        timestamp.erase(del[i]);   // <--
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

在一个unordered_map,擦除可以使迭代器无效.因此,在您遍历时无法擦除 - 尝试提出不同的算法.(我假设你的问题的一些版本,包括timestamp作为一个unordered_map-尽管在你的代码,这种类型的无参考).

  • @Surt如果`ite`当前是删除键的迭代器,则不行."擦除元素的引用和迭代器无效.其他迭代器和引用不会失效." (2认同)