Boost :: Multi_Indexを探索しながらSIGSEGV
-
11-12-2019 - |
質問
私はこのSegfaultを把握し、いくつかの助けを求めることを決めました。
boost::multi_index
コンテナがあり、(string, string, double)
を含み、ある時点でSegfaultにヒットします。
これは私のコードの単純化されたバージョンです:
#include<iostream>
....
// mySet is a multi_index container which contains <(string str1), (string str2), (double val)>
typedef mySet::index<str1>::type set_by_str1;
...
for(unsigned int i=0; i < token.size(); ++i)
{
set_by_str1::iteration it = myContainer.get<str1>().find(token[i]);
while(it->str1() == token[i])
{
cout << it->str1() << ", " << it->str2() << ", " << it->val << endl;
}
*it++;
}
.
このコードはかなりうまく機能しているようですが、それが特定のトークンに当たったときにのみクラッシュします。(反対に言えば、これがトークンを満たしていないときはクラッシュすることはありません)。
it
はコンテナ自体の範囲を超えているが、それがどのように起こるかを理解していないため、これが起こると思います。
GDBエラーメッセージ表示:
Program received signal SIGSEGV, Segmentation fault.
0x08052e83 in std::string::size (this=0x806e190) at /usr/include/c++/4.4/bits/basic_string.h:629
629 { return _M_rep()->_M_length; }
(gdb) bactrace full
#0 0x08052e83 in std::string::size (this=0x806e190) at /usr/include/c++/4.4/bits/basic_string.h:629
No locals.
#1 0x08050475 in std::operator<< <char, std::char_traits<char>, std::allocator<char> > (__os=..., __str=...)
at /usr/include/c++/4.4/bits/basic_string.h:2503
No locals.
#2 0x0804e4e0 in MyClass:MyFunction (this=0xbffff534) at src/MyCode.cpp:353 (This is where while condition exists)
... dump of HUGE trace for multi_index ...
.
トークンベクトルのせいではなく、とit->str1()
を呼び出すと明らかにクラッシュします。どうやってこれを防ぐことができますか?
if(it == myContainer.get<str1>().end()) break;
の下の*it++
を追加しようとしましたが、役に立ちませんでした。
誰かが私にいくつかの手がかりを与えますか?
ありがとうございました!
解決
あなたのコードには多くの問題があります:
-
token[i]
と同等のコンテナに要素がない場合は、find
が参照されていないend()
を返します。 -
while
ループの間にit
はコンテナの終わりに達することができ、またあなたはそれを尊重することができないでしょう。 -
find
は、token[i]
と同等のキーを持つ最初の要素を取得しません。これはおそらくあなたが望むものです。代わりにlower_bound
を使用してください。私はあなたが次のようにコードを変更することを勧めます:
.pair<set_by_str1::iterator, set_by_str1::iterator> p = myContainer.get<str1>().equal_range(token[i]); while(p.first!=p.second) { cout << p.first->str1() << ", " << p.first->str2() << ", " << p.first->val << endl; ++(p.first); }
他のヒント
it->str1()
はNULLまたはtoken[i]
のいずれかがNULLです。
それらがnullでないことを確認し、セグメンテーション障害が消えます。
while
をif
に置き換えることもできます。nofollow ">ここ、アイテムが見つからない場合、それは最後の要素のイテレータとしてイテレータを返します。これは、nullとしてstr1
を持つことがあります。
また、トークン文字列全体を印刷するだけではなく、トークン文字列文字の上にイテレータを文字列文字でイテレータに印刷しますか?(少なくとも私はあなたのサンプルとして、それが文字列であると思います。コードはそれを定義しません)。