目录
问题
最近撸代码时发现一个诡异的事情, 其中用到了一个如下的数据结构
typedef unordered_map<char *, SomeType, MyHasher, MyComparer> MyMap;
姑且不论这奇葩的结构, 简单概括一下就是:
- key 是手动管理内存的字符串 (添加时手动 malloc, 删除时手动 free, 当然塞进 map 后不会修改)
- 使用自定义 hash 和 compare 函数来提供 unordered_map 所需的功能
于是, 问题来了, 以下是最简复现代码:
// 插入
MyMap m;
char *key = my_malloc_and_copy("123");
m[key] = SomeType();
// 删除全部
MyMap tmp = m;
m.clear();
for(MyMap::iterator it = tmp.begin(); it != tmp.end(); ++it)
{
free(it->first);
}
咋一看很标准的 iterator 遍历删除对不对? 很可惜的告诉你, 那个循环会进入两次, 然后理所当然的挂在第二次的 free 上面
原因
原因一句话就可以概括:
对于 unordered_map, ++it 的时候需要计算当前 it->first
的 hash 值, 然而此时已被 free 了
后记
- 在 mac 版 Qt 上遇到该问题, 同样的代码在其他平台下不会复现 (论跨平台代码的重要性)
- 比较奇葩的是, 断点调试下不会挂掉, 而直接运行会挂掉, 导致找这个问题时花了好多时间
转载请注明来自: http://zsaber.com/blog/p/78
既然都来了, 有啥想法顺便留个言呗? (无奈小广告太多, 需审核, 见谅)