(文字列、オブジェクト*)をハッシュテーブルに挿入(C ++)
質問
この質問は、ハッシュの作成に関する前の質問の派生物です。文字列キーとポインターをデータとして保存するテーブル。ハッシュテーブルにエントリを追加しようとすると、構築後にセグフォールトが発生します。どんな構文が適切かについて、私はまだ非常に混乱しています。
現在、(以前のポスターのおかげで)私は持っています:
// Simulation.h
#include <ext/hash_map>
using namespace __gnu_cxx;
...
typedef struct { size_t operator()( const string& str ) const
{ return __gnu_cxx::__stl_hash_string( str.c_str() ); } } strhash;
struct eqstr {
bool operator()(string s1, string s2) const {
return ( s1.compare(s2) == 0 );
}
};
....
hash_map< string, Strain *, strhash, eqstr > strainTable;
シミュレーションコンストラクターには、次のものがあります。
// Simulation.cpp
Simulation::Simulation() : ... {
string MRCA;
for ( int b = 0; b < SEQ_LENGTH; b++ ) {
int randBase = rgen.uniform(0,NUM_BASES);
MRCA.push_back( BASES[ randBase ] );
}
Strain * firstStrainPtr;
firstStrainPtr = new Strain( idCtr, MRCA, NUM_STEPS );
strainTable[ MRCA ]= firstStrainPtr; // <-- Hash table initialization
....
}
これはうまくいくようです。次の挿入を試行すると、セグエラーが発生します。
void Simulation::updateSimulation( double t ) {
....
// Add mutants to liveStrains() and strainTable
vector< Strain * >::const_iterator mItr = newMutants.begin();
for ( mItr = newMutants.begin(); mItr != newMutants.end(); ++mItr ) // for each mutant in deme
{
string mutantSeq = ( *mItr )->getSequence();
cout << "mutantSeq is " << mutantSeq << endl; // <-- This is fine
liveStrains.push_back( *mItr );
strainTable[ mutantSeq ] = *mItr; // <-- Seg fault happens here
}
newMutants.clear();
....
}
SGIドキュメントのオペレーターに関する3番目のメモを読む[] 、これは問題ないようです。どうしましたか?デバッグ時間を節約するために、マップコンテナに切り替えることを考えています...
更新
初期化に関する何かが間違っているようです。
に着いたらstrainTable[ mutantSeq ] = *mItr;
デバッガは&quot; EXC_BAD_ACCESS&quot;を報告します。にジャンプして
_Node* __first = _M_buckets[__n];
hashtable.hの。
解決
診断アプローチとして、実際には次の2つの命令を実行します。
- 参照を返す
strainTable
のルックアップ - イテレータの参照解除
- 参照への値の割り当て
ここでは、分割と征服
のアプローチを採用できます。
strainTable[ mutantSeq ] = *mItr; // <-- Seg fault happens here
なる
Strain*& aReference = strainTable[ mutantSeq ];
Strain* const aPtr = *mItr;
aReference = aPtr;
(これは一般的なアドバイスです)
segフォールトはどの行で発生しますか?スタックの最初の10フレームを持つことは可能ですか?
Googleの検索中に、このバグレポートを見つけました。 。これは、 hash_map
に問題がある可能性があることを示唆しています...
unordered_map 可能であれば、レガシーコンテナと見なされた hsah_map
の修正に時間がかからないことが明確に示されているため(これは2005年でした...)。 GCC 4.xを使用する場合は利用可能であることに注意してください(3.xについては不明)
主な利点は、 std :: string
で hash
構造と比較述語
がすでに機能しているため、必要がないことです。自分で実装してください:)
あなたがしなければならないのは、コンパイラにこれがある場合、これを書くことです:
#include <tr1/unordered_map>
typedef std::tr1::unordered_map<std::string, Strain*> strain_hash_map;
他のヒント
このコードに悪いところはありません。エラーは別の場所にある必要があります。たぶん、(* mItr)-&gt; getSequence()の値は、無効な文字列、またはそのようなものを与えています。
最適化として、operator()は文字列const&amp;を取ることができます単なる文字列の代わりに。
恥ずかしい&quot; solution&quot;クラスヘッダーファイルで2次元配列のフルサイズを宣言していないことを発見したということです。コンストラクターで配列を初期化したときに、ハッシュテーブルのスペースの一部が上書きされました。
ここでの提案のおかげで、私はstd :: tr1 :: unordered_mapに移動しました!