1

C スタイルの文字列ペアを格納するために C++ hash_map を使用しています。この場合、すべてのキーは一意である必要があります...

私の問題は、これを複数回実行してストレステストを行うと、重大なメモリリークが発生することです。

テストでこれらのキーがどれも同一でない場合、メモリ リークはありません。しかし、同じキーでは別の話です...

hash_map (これは Google のsparsehash ですが、SGI 関数を完全に実装しています)

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

検索したところ、同じキーを持つ key/val ペアを置き換える関数が見つかりませんでした。

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

最初の重複キーでクラッシュします。

私がこれを試した2つの方法。オプション 1 では、消去時にセグメンテーション違反が発生します (これにも困惑します)。オプション 2 では問題が解決されず、メモリ リークが発生します。たぶん、私はこれをすべて間違っているだけです。

はい、C++ 文字列を使用できることはわかっていますが、使用したくありません。組み込みシステムのために、この本当の光を維持しようとしています。どんな助けでも大歓迎です...

4

3 に答える 3

2

イテレータを使用して、hash_map内で直接値を変更できます。

    ret = it->second;

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

それはより速くそしてより安全な解決策になるでしょう。

別のhash_mapメソッドを試して、イテレータではなくキーで消去することもできます。

size_type erase(const key_type& k)
于 2009-07-20T02:45:40.477 に答える
0

何か奇妙なことが起こっているようです。あなたがしていることはうまくいくはずなので、hash_mapを誤用していると思われます。実際、あなたが最初に行っていたことがうまくいったはずです。

すなわち。

values[k] = v;

存在する場合は、すでに存在するものをキー「k」に置き換える必要があります。

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

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

于 2009-07-19T23:33:27.603 に答える
0

コードに単純なエラーがあったことがわかりました。キーを見つけるのに間違ったイテレータを使用していたのです。

ただし、これに遭遇する可能性のある人々のためのいくつかのポイント:
- 文字列ではなくポインターを格納しています。したがって、add キーを追加せずに ->second を変更するか、エントリ全体 (およびその文字列) を消去しない限り、重複したキー (C 文字列自体) は絶対に削除されません。
すべての文字列メモリを free() する必要があります。ハッシュの場合、ハッシュ自体が破棄される前。
- 重複したキーで values[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;
}

どちらの方法でも機能します。皆さんありがとう。

于 2009-07-20T04:43:18.820 に答える