重复键时删除STL哈希映射上的键/值时出现问题 我使用C++ HasyMax存储一些C风格字符串对。对于这种情况,所有密钥都应该是唯一的

重复键时删除STL哈希映射上的键/值时出现问题 我使用C++ HasyMax存储一些C风格字符串对。对于这种情况,所有密钥都应该是唯一的,c++,stl,hashmap,C++,Stl,Hashmap,我的问题是,在多次运行压力测试时,内存严重泄漏 如果测试中的所有键都不相同,则不存在内存泄漏。但用相同的钥匙,情况就不同了 hash_映射(这是Google的,但它完全实现了SGI函数) 将只添加一个新的对,即使密钥相同。(我认为这个行为应该是可切换的)-这只是一个hash_映射 因此,我有一个功能来检查密钥是否存在,它是否替换了val,如果不只是添加一对新密钥: char *confFile::replaceOrStoreVal( char *k, char *v ) { char *ret

我的问题是,在多次运行压力测试时,内存严重泄漏

如果测试中的所有键都不相同,则不存在内存泄漏。但用相同的钥匙,情况就不同了

hash_映射(这是Google的,但它完全实现了SGI函数)

将只添加一个新的对,即使密钥相同。(我认为这个行为应该是可切换的)-这只是一个hash_映射

因此,我有一个功能来检查密钥是否存在,它是否替换了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
它在第一个重复密钥上崩溃

我试过两种方法。选项1导致擦除时出现segfault(这也让我感到困惑)。选项2只是没有解决问题,仍然存在内存泄漏。也许我只是做错了


是的,我知道我可以使用C++字符串,但我不想使用。对于嵌入式系统来说,试图保持这种真实感。非常感谢您的帮助……

似乎发生了一些奇怪的事情。我怀疑你误用了hash_映射,因为你所做的应该是有效的。事实上,你最初所做的应该是有效的

应将已存在的内容替换为键“k”(如果存在)

我可以建议你用标准的STL映射代替谷歌的稀疏散列映射吗?这样,您就可以验证您的算法是否有效


然后,如果您将std::map替换为稀疏散列映射,并且该映射出现故障,那么问题要么在于稀疏散列映射,要么在于您使用它的方式

您可以通过迭代器直接在哈希映射内更改值:

    ret = it->second;

    it->second = v; // end option 2
}
size_type erase(const key_type& k)
这将是更快、更安全的解决方案

您还可以尝试另一种哈希映射方法,通过键而不是迭代器进行擦除:

    ret = it->second;

    it->second = v; // end option 2
}
size_type erase(const key_type& k)

事实证明,我的代码有一个简单的错误:我使用了错误的迭代器来查找密钥

然而,对于可能遇到这种情况的人,有两点需要注意:
-您正在存储指针,而不是字符串。因此,重复的键绝对不会被删除(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;
}
char*confFile::replaceOrStoreVal(char*k,char*v){
char*ret=NULL;
值。设置删除键(\u DIST\u key);
稀疏散列映射::迭代器it=
值。查找(k);
if(it==values.end())
值[k]=v;
否则{
ret=it->second;
它->秒=v;
免费的(k);//我们不需要这个——我们已经把它储存起来了。
//char*t=(char*)it->first;
//ret=it->second;
//values.erase(it);//这里有一个输入错误
//自由(t);
//值[k]=v;
}
返回ret;
}

这两种方法都有效。谢谢大家。

您显然没有发布真正的代码-请尝试这样做,这会让每个人的生活更轻松。代码直接来自emacs。我添加了更多的帮助。除了如果钥匙已经在那里,它将不会免费。所以仍然存在内存泄漏。此外,你不能总是释放钥匙,不管发生什么,b/c它将无法在钥匙上进行strcmp。是的,你是对的。我想在我的答案底部加上一句,在地图中使用char*需要非常小心,但我删除了这一点。再想一想,我应该把它留在家里。
size_type erase(const key_type& k)
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;
}