所有。我正在开发使用系统主机文件阻止广告的软件,但是代码仍然存在。
我有一个自定义类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/
答案 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
答案 2 :(得分:1)
擦除矢量成员时,它会使迭代器失效。
Std :: lists旨在允许您在中间删除而不会使迭代器失效。因此,对于这个特定的操作,它将允许最简单的代码。
但是,向量可能仍然会更好整体IF性能是一个问题。只有当列表具有足够多的成员并且您在中间删除时,列表才会看到它允许的较不复杂的代码的性能优势。
答案 3 :(得分:0)
viter
迭代的集合后, viter
无效。
答案 4 :(得分:0)
我没有看到代码中的任何错误。我认为你应该运行你的调试版本,并在delHost()中放置断点。逐步找出导致seg故障问题的原因。