首页 > 解决方案 > std::list 和垃圾收集算法

问题描述

我有一台服务器,可根据要求将 2 名玩家放在一起,并Game在新线程中开始游戏。

struct GInfo {Game* game; std::thread* g_thread};

while  (true) {
    players_pair = matchPlayers();
    Game* game = new Game(players_pair);
    std::thread* game_T = new std::thread(&Game::start, game);
    GInfo ginfo = {game, game_T}
    _actives.push_back(ginfo);    // std::list
}

我正在编写一个在另一个线程中运行的“垃圾收集器”,以清除已终止游戏的内存。

void garbageCollector() {
    while (true) {
        for (std::list<Ginfo>::iterator it = _actives.begin(); it != _actives.end(); ++it) {
            if (! it->game->isActive()) {
                delete it->game; it->game = nullptr;
                it->g_thread->join();
                delete it->g_thread; it->g_thread = nullptr;
                _actives.erase(it);
            }
        }
        sleep(2);
    }
}

这会产生一个段错误,我怀疑这是因为_active.erase(it)处于迭代循环中。为了进行故障排除,我做了_actives一个std::vector(而不是std::list)并应用了相同的算法,但使用索引而不是迭代器,它工作正常。

有没有解决的办法?

算法、数据结构用的好吗?有没有更好的垃圾收集方法?

帮助表示赞赏!

标签: c++algorithmliststlgarbage-collection

解决方案


如果您查看erase方法的文档,它会在被删除的元素之后返回一个迭代器。

使用它的方法是将返回的值分配给您的迭代器,就像这样。

for (std::list<Ginfo>::iterator it = _actives.begin(); it != _actives.end();) {
    if (! it->game->isActive()) {
        delete it->game; it->game = nullptr;
        it->g_thread->join();
        delete it->g_thread; it->g_thread = nullptr;
        it = _actives.erase(it);
    }
    else {
        ++it;
    }
}

由于从获取返回值erase将迭代器推进到下一个元素,因此我们必须确保在发生这种情况时不要增加迭代器。

在不相关的注释中,以下划线开头的变量名称通常保留给编译器的内部,应该在您自己的代码中避免使用。


推荐阅读