You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迭代std::unordered_map触发Segmentation Fault问题排查求助

解决std::unordered_map迭代删除时的Segmentation Fault问题

看起来你遇到的段错误根源在于write_blacklist()函数中对std::unordered_map迭代器的错误处理——当你删除元素后仍然盲目递增迭代器,导致访问了失效的迭代器(空指针)。

问题分析

从GDB的回溯信息可以看到,崩溃发生在write_blacklist()的第68行++a处,此时迭代器的_M_next指针为0x0,说明我们在迭代器已经失效(或指向end())的情况下仍尝试递增它。

看你的这段核心代码:

auto a = ips.begin();
while (a != ips.end()) {
    if (a->second < max_attempts_) {
        a = ips.erase(a);
    } else {
        if (a->second > max_attempts_) {
            if (check_reports(a->first) < max_reports_) {
                a = ips.erase(a);
            }
        }
        ++a;  // 危险!删除元素后仍会执行这行
    }
}

问题出在当你通过a = ips.erase(a)删除元素后,a已经被更新为下一个有效的迭代器,但之后代码仍会执行++a。如果erase返回的已经是ips.end(),再执行++a就会访问空内存,直接触发段错误。

第一次迭代时可能刚好没有触发这种边界情况(比如没有删除到最后一个元素),但第二次迭代时,数据状态触发了这个问题,导致崩溃。

修复方案

调整迭代器的处理逻辑,只有在没有删除元素的时候才递增迭代器:

void BruteBlock::write_blacklist(std::unordered_map<std::string, int> &ips, const std::string &output_file) {
    std::ifstream is(output_file.c_str());
    if (!is) throw std::runtime_error("Error opening blacklist");
    if (ips.empty()) return;

    // ignore duplicates
    std::string buf;
    while (std::getline(is, buf)) {
        if (ips.find(buf) != ips.end()) {
            ips.erase(buf);
            std::cout << buf << " already in blacklist, skipping..." << '\n';
        }
    }

    // delete the IPs that don't meet the criteria
    auto a = ips.begin();
    while (a != ips.end()) {
        if (a->second < max_attempts_) {
            // 删除后,a自动指向下一个元素,无需递增
            a = ips.erase(a);
        } else if (a->second > max_attempts_) {
            if (check_reports(a->first) < max_reports_) {
                a = ips.erase(a);
            } else {
                // 不删除,递增迭代器
                ++a;
            }
        } else {
            // a->second == max_attempts_,保留,递增迭代器
            ++a;
        }
    }

    // write the remaining IPs to the blacklist
    std::ofstream os(output_file.c_str(), std::ios_base::app);
    if (!os) throw std::invalid_argument("Error opening blacklist file");
    for (auto f : ips) {
        if ((f.second > max_attempts_) && (check_reports(f.first) > max_reports_)) {
            os << f.first << '\n';
            std::cout << f.first << " had " << f.second << " failed attempts and " << check_reports(f.first) << " abuse reports, adding to blacklist...\n";
        }
    }
}

额外优化建议

  • 可以把check_reports(a->first)的结果缓存下来,避免重复调用,提升性能。
  • 注意std::unordered_map::erase(key)会遍历整个哈希表查找元素,如果你已经有迭代器的话,优先使用erase(iterator)版本,效率更高。

内容的提问来源于stack exchange,提问作者user9232663

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:52:40