C ++ Vector删除特定项目,但是段错误

时间:2011-03-31 01:36:38

标签: c++ vector segmentation-fault

所有。我正在开发使用系统主机文件阻止广告的软件,但是代码仍然存在。

我有一个自定义类HostEntry,其中包含必要的信息,例如目标主机,要阻止的主机,目标主机的IP等等。

在HostsManager类中,它保留一个向量以跟踪添加的所有主机。为了完全阻止主机,我必须添加example.com AND www.example.com,但是当我迭代向量时,它只会删除以“www”开头的条目。而没有。如果你第二次尝试删除它(只有条目缺少“www。”)它会出现段错误,我不知道为什么。

void HostsManager::delHost(std::string blockedhost) {
    strip(blockedhost);
    string tmp; // yes I know it's not great practice to do it like this, but it was for debug reasons
    for (vector<HostEntry>::iterator viter = hosts.begin(); viter != hosts.end(); ++viter) {
        tmp = viter->getHost();
        if (tmp == blockedhost || tmp == ("www." + blockedhost)) {
            viter = hosts.erase(viter);
        }
    }
}

对该特定功能的示例调用:

HostsManager mgr;
mgr.delHost("mysite.com"); // this deletes "www.mysite.com" but not "mysite.com" - whether or not you call delHost() with the "www." prefix
mgr.delHost("mysite.com"); // if you call it a second time, it segfaults O.o

非常感谢您的帮助。

编辑:我将从erase()调用返回的值赋给了viter,结果相同。我仍然不知道为什么会这样。

如果您需要所有代码,请访问http://paste.pocoo.org/show/363051/

5 个答案:

答案 0 :(得分:2)

通常最好使用std::remove_if从向量中删除多个项目;它以线性时间而不是二次方式运行,避免担心迭代器失效。

可能看起来像这样:

hosts.erase(std::remove_if(hosts.begin(), 
                           hosts.end(), 
                           [&blockedhost](const HostEntry& entry) {
                               return entry.getHost() == blockedhost || 
                                      entry.getHost() == "www." + blockedhost;
                           }),
            hosts.end());

你可以在没有C ++ 0x lambdas的情况下通过结构来完成类似的事情来比较:

struct RemoveBlockedHost {
    RemoveBlockedHost(const std::string& s): blockedHost(s) {}
    bool operator () (const HostEntry& entry) {
        return entry.getHost() == blockedHost || entry.getHost() == "www." + blockedHost;
    }
    const std::string& blockedHost;
};

hosts.erase(std::remove_if(hosts.begin(), hosts.end(), RemoveBlockedHost(blockedhost)), hosts.end());

答案 1 :(得分:1)

您正在迭代正在迭代的矢量中的项目!您想将viter设置为erase返回的值。请参阅vector::erase

的C ++文档

答案 2 :(得分:1)

擦除矢量成员时,它会使迭代器失效。

Std :: lists旨在允许您在中间删除而不会使迭代器失效。因此,对于这个特定的操作,它将允许最简单的代码。

但是,向量可能仍然会更好整体IF性能是一个问题。只有当列表具有足够多的成员并且您在中间删除时,列表才会看到它允许的较不复杂的代码的性能优势。

答案 3 :(得分:0)

修改viter迭代的集合后,

viter无效。

答案 4 :(得分:0)

我没有看到代码中的任何错误。我认为你应该运行你的调试版本,并在delHost()中放置断点。逐步找出导致seg故障问题的原因。