我使用C ++ hash_map来存储一些C风格的字符串对。对于这种情况,所有键都应该是唯一的......
我的问题是在多次运行压力测试时出现严重的内存泄漏。
如果测试中的这些键都不相同,则没有内存泄漏。但是使用相同的按键却是一个不同的故事...
hash_map(这是Google的sparsehash,但它完全实现了SGI功能)
sparse_hash_map<const char*, char *, hash<const char*>, eqstr> values;
我搜索并找不到替换具有相同键的键/值对的函数。
values[k]=v;
只会添加一对新对,即使密钥相同也是如此。 (我认为应该可以切换的行为) - 这只是一个hash_map.insert()
所以我有一个函数检查密钥是否存在,是否确实替换了val,如果不是只添加一对:
char *confFile::replaceOrStoreVal( char *k, char *v ) {
char *ret = NULL;
values.set_deleted_key(_DIST_KEY);
sparse_hash_map<const char*, char *, hash<const char*>, eqstr>::iterator it =
values.find(k);
if(it == values.end())
values[k] = v;
else {
// ret = it->second; // option 1
//it->second = v; // end option 1
//option 2
char *t = (char *) it->first;
ret = it->second;
values.erase( iter ); <--- seg fault here
free(t);
values[k] = v; // end option 2
}
return ret;
} ... and ret is later free()ed
最初对添加如下:
old = replaceOrStoreVal(recordname, value);
它在第一个重复键上崩溃。
我试过这两种方式。选项1导致擦除的段错误(这也让我感到困惑)。选项2只是没有解决问题,仍然有内存泄漏。也许我只是做错了。
是的,我知道我可以使用C ++字符串,但我不想这样做。试图为嵌入式系统保持这种真正的亮点。任何帮助表示赞赏...
答案 0 :(得分:2)
您可以通过迭代器直接在hash_map中更改值:
ret = it->second;
it->second = v; // end option 2
}
这将是更快,更安全的解决方案。
您还可以尝试使用另一个hash_map方法按键擦除,而不是通过迭代器:
size_type erase(const key_type& k)
答案 1 :(得分:0)
似乎有些奇怪的事情发生了。我怀疑你是在滥用hash_map,因为你正在做的事情应该有效。事实上,你原本做的事应该有效。
即
values[k] = v;
如果存在,则应替换已存在的密钥“k”。
我建议你用标准的STL地图替换Google的sparse_hash_map吗?这样您就可以验证您的算法是否有效。
然后,如果用sparse_hash_map替换std :: map并且它中断,则问题出在sparse_hash_map或你使用它的方式上。
答案 2 :(得分:0)
事实证明我的代码只有一个简单的错误:我使用了错误的迭代器来找到密钥。
然而,对于可能遇到这种情况的人来说,有几点: - 你存储指针,而不是字符串。因此,除非您不添加添加键,只需更改 - &gt;秒,或删除整个条目(及其字符串),否则绝对不会删除重复键(C字符串本身) - 在哈希本身被破坏之前,你必须释放()哈希的所有字符串内存 - 重复使用值[k] = v重复键会导致泄漏。
工作职能:
char *confFile::replaceOrStoreVal( char *k, char *v ) {
char *ret = NULL;
values.set_deleted_key(_DIST_KEY);
sparse_hash_map<const char*, char *, hash<const char*>, eqstr>::iterator it =
values.find(k);
if(it == values.end())
values[k] = v;
else {
ret = it->second;
it->second = v;
free(k); // we dont need this - we already have it stored.
// char *t = (char *) it->first;
//ret = it->second;
//values.erase( it ); // has a typo here
//free(t);
//values[k] = v;
}
return ret;
}
任何一种方法都可行。谢谢大家。