2009-07-19 6 views
1

Cスタイルの文字列ペアを格納するためにC++のhash_mapを使用しています。そして、すべてのキーは、このケースで一意でなければなりません。重複キーの場合のSTL hash_mapのキー/値の削除に関する問題

これは、複数の実行でストレステストを行うと重大なメモリリークです。

これらのキーが一致しない場合、メモリリークは発生しません。しかし、同一のキーその別の話...

hash_map(これはGoogleのsparsehashですが、それは完全にSGIの機能を実装)

sparse_hash_map<const char*, char *, hash<const char*>, eqstr> values; 

と私は/検索し、キーを交換する機能を見つけることができませんでした同じキーを持つvalペア。

values[k]=v; 

は、キーが同じでも新しいペアを追加します。 (これはトグル可能でなければならないと思う) - これはhash_map.insert()以外の何ものでもありません。

私はキーが存在するかどうかをチェックする機能を持っています。新しいペア:最初に

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); 

それは最初の重複キーの上にクラッシュします。

2つの方法でこれを試しました。オプション1を指定すると消去時にセグメンテーションが発生します。オプション2は問題を解決せず、メモリリークがまだあります。たぶん私はこれをすべて間違ってやっているかもしれません。

はい、私はC++の文字列を使うことができますが、私はしたくないと思います。組み込みシステムの場合、これを真実に保つことを試みています。どんな助けにも感謝しています...

+1

実際のコードを投稿していないことは明らかです。そうしてみると、誰もが簡単に使えるようになります。 –

+0

そのコードはemacsから直接出ます。私はもう少し手伝ってくれました。 – EdH

答えて

2

あなたはイテレータを通じてhash_map内の値を直接変更することができます。

ret = it->second; 

    it->second = v; // end option 2 
} 

それはより速く、より安全なソリューションとなります。

ます。またキーではなく、イテレータによって消去する他のhash_mapの方法を試すことができます。

size_type erase(const key_type& k) 
0

奇妙なことが起こっているようです。あなたがやっていることはうまくいくはずだから、あなたはhash_mapを悪用していると思います。実際に、元々やっていたことが働いていたはずです。

ie。

values[k] = v; 

すでに存在していたものを存在させた場合は、これを「k」に置き換える必要があります。

Googleのsparse_hash_mapの使用方法を標準のSTLマップに置き換えることをお勧めしますか?そうすれば、あなたのアルゴリズムが動作することを確認することができます。

次に、std :: mapをsparse_hash_mapに置き換えて壊れた場合、問題はsparse_hash_mapまたは使用している方法のいずれかです。

+0

ただし、キーが既にそこにある場合、それはfree'dになりません。だからまだメモリリークがあります。また、鍵をstrcmpで実行することができなくなるだけで、鍵を解放することはできません。 – EdH

+0

はい、そうです。私はマップのchar *を使用することは非常に気をつけなければならないと私の答えの一番下に追加しようとしていましたが、私はそのビットを削除しました。それ以上の反射で、私はそれを残しておくべきだった。 – Rodyland

0

それは私のコードが判明単純なエラーが発生しました:私は鍵を見つけるために、間違ったイテレータを使用していました。

ただし、これに遭遇する可能性のある人々のための2点:
- 文字列ではなくポインタを格納しています。あなたが追加キーを追加せず、 - >秒を変更するか、またはエントリ全体(そしてその文字列)を消去しない限り、重複キーは絶対に削除されません(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; 
} 

いずれかの方法で作業を行います。機能を作業

。皆さんありがとう。

関連する問題