unordered_map 手动管理元素内存时的注意事项

By | 2015-12-18

问题

最近撸代码时发现一个诡异的事情, 其中用到了一个如下的数据结构

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

既然都来了, 有啥想法顺便留个言呗? (无奈小广告太多, 需审核, 见谅)

Category: C++

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注