在 BFS 实现中,由于迭代器引用无效而发生崩溃
作者: wuxianggujun创建于 2025年4月7日更新于 2025年4月7日
描述
BFS 算法在图遍历过程中出现"异常 0x80000003"(访问权限受限)和断言失败"无法解引用结尾列表迭代器",导致程序崩溃。崩溃发生在处理队列元素和访问图结构时。
重现步骤
- 构建并执行提供的 BFS 实现
- 使用测试数据初始化图:
graph.insert({"you", {"alice", "bob", "claire"}});
... // 其他节点- 从"you"节点开始搜索
- 程序在队列处理过程中崩溃
错误日志
Exception 0x80000003 encountered at address 0x7ff6f69aba73
File: MSVC include\list Line: 147
Expression: cannot dereference end list iterator根本原因分析
- 悬浮引用
- 原始代码使用
T& person = search_queue.front()后跟着pop() - 删除元素后对队列数据创建了无效引用
- 后续访问
person导致了未定义的行为
- 不安全的迭代器解引用
- 直接解引用
graph.find()->second而不进行存在性检查 - 如果未找到键,则有可能访问
end()迭代器
- 不完整的图验证
- 在处理好友列表时没有验证节点的存在性
- 缺失图节点可能会发生空指针解引用
建议的修复
// 1. 安全的队列元素访问
T person = search_queue.front(); // 使用复制而不是引用
search_queue.pop();
// 2. 在访问前验证图节点
auto start_it = graph.find(name);
if (start_it == graph.end()) {
return false; // 处理缺失的起始节点
}
// 3. 安全处理好友列表
auto person_it = graph.find(person);
if (person_it != graph.end()) {
for (const auto& friend_name : person_it->second) {
search_queue.push(friend_name);
}
}验证
在应用这些更改后:
- 测试案例成功找到"thom"作为芒果卖家
- 缺失节点的压力测试不再崩溃
- Valgrind/内存检查显示清洁报告
严重程度: 严重(崩溃/数据损坏)
优先级: P1(必须修复)
受影响的版本: 所有版本,2023-04-07 之前的版本
建议的其他改进
- 添加单元测试:
- 缺失起始节点
- 节点具有空的好友列表
- 多个连续的卖家
- 实现图验证包装函数
- 添加缺失节点的错误日志
环境
- 操作系统:Windows 10/11
- 编译器:MSVC 2022(v14.34-17.8)
- 构建配置:调试 x64
- STL 版本:MSVC STL 2022
附件 - 完整修复代码
内容来源: egonSchiele/grokking_algorithms