5

boost::split の最初のパラメータとして boost::unordered_set を渡すことがコーシャかどうかは誰にもわかりませんか? libboost1.42-dev では、これにより問題が発生するようです。問題を引き起こす小さなサンプル プログラムを次に示します。test-split.cc と呼びます。

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/unordered_set.hpp>
#include <string>

int main(int argc, char **argv) {
  boost::unordered_set<std::string> tags_set;
  boost::split(tags_set, "a^b^c^",
               boost::is_any_of(std::string(1, '^')));
  return 0;
}

次に、次のコマンドを実行すると:

g++ -o test-split test-split.cc; valgrind ./test-split

次のような valgrind で多くの苦情を受け取ります (タイミングによって異なるようですが、valgrind なしでコアダンプが表示されることもあります)。

==16843== Invalid read of size 8
==16843==    at 0x4ED07D3: std::string::end() const (in /usr/lib/libstdc++.so.6.0.13)
==16843==    by 0x401EE2: unsigned long boost::hash_value<char, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /tmp/test-split)
...
==16843==    by 0x402248: boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >& boost::algorithm::split<boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >, char const [26], boost::algorithm::detail::is_any_ofF<char> >(boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >&, char const (&) [26], boost::algorithm::detail::is_any_ofF<char>, boost::algorithm::token_compress_mode_type) (in /tmp/test-split)
==16843==    by 0x40192A: main (in /tmp/test-split)
==16843==  Address 0x5936610 is 0 bytes inside a block of size 32 free'd
==16843==    at 0x4C23E0F: operator delete(void*) (vg_replace_malloc.c:387)
==16843==    by 0x4ED1EE8: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/libstdc++.so.6.0.13)
==16843==    by 0x404A8B: void boost::unordered_detail::hash_unique_table<boost::unordered_detail::set<boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> > >::insert_range_impl<boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string, char const*>, boost::algorithm::split_iterator<char const*>, boost::use_default, boost::use_default> >(std::string const&, boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string, char const*>, boost::algorithm::split_iterator<char const*>, boost::use_default, boost::use_default>, boost::transform_iterator<boost::algorithm::detail::copy_iterator_rangeF<std::string, char const*>, boost::algorithm::split_iterator<char const*>, boost::use_default, boost::use_default>) (in /tmp/test-split)
...
==16843==    by 0x402248: boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >& boost::algorithm::split<boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >, char const [26], boost::algorithm::detail::is_any_ofF<char> >(boost::unordered_set<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::string> >&, char const (&) [26], boost::algorithm::detail::is_any_ofF<char>, boost::algorithm::token_compress_mode_type) (in /tmp/test-split)
==16843==    by 0x40192A: main (in /tmp/test-split)

これは Debian Squeeze ボックスです。関連するシステム情報は次のとおりです。

$ g++ --version
g++ (Debian 4.4.5-2) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ dpkg -l | grep boost
ii  libboost-iostreams1.42.0            1.42.0-4                     Boost.Iostreams Library
ii  libboost1.42-dev                    1.42.0-4                     Boost C++ Libraries development files
$ uname -a
Linux gcc44-buildvm 2.6.32-5-amd64 #1 SMP Fri Sep 17 21:50:19 UTC 2010 x86_64 GNU/Linux

ただし、libboost1.42-dev を libboost1.40-dev にダウングレードすると、コードは正常に動作するようです。これはboost 1.42のバグですか、それともシーケンスを処理できないコンテナを渡すことでboost::splitを誤用していますか? ありがとう!

4

3 に答える 3

2

これは、boost-usersメーリングリストで、boost::unordered_set実装のバグであることが確認されました。メーリングリストに利用可能なパッチがあり、修正はすぐにチェックインされ、できればブースト1.45に間に合うようになります。

Boost-users:パッチ

ブーストユーザー:確認

これを調べてくれてありがとう!

于 2010-10-21T17:29:50.233 に答える
0

どうやら、答えはno yesです。

unordered_set次のコードを使用すると、正常に動作している間、コンパイル時の警告とランタイム アサート (Visual C++ v10) が表示されvectorます (末尾の '^' による最後の要素の空の文字列は別として)。

boost::unordered_set<std::string> tags_set;
vector<string> SplitVec; // #2: Search for tokens
boost::split( SplitVec, "a^b^c^", boost::is_any_of("^") ); 
boost::split( tags_set, "a^b^c^", boost::is_any_of("^") );

ソース ( string) とターゲット コンテナ間の反復子の互換性が問題です。警告エラーを投稿しますが、これは「戦争と平和」テンプレート警告の 1 つです。

編集:

これは Boost のバグのように見えunordered_setますか? 以下を使用すると、期待どおりに動作します。

std::unordered_set<std::string> tags_set_std;
boost::split( tags_set_std, string("a^b^c^"), boost::is_any_of(string("^")) );
于 2010-10-20T19:30:05.780 に答える
0

答えはイエスであるべきだと思います。

ヘッダー (split.hppおよびiter_find.hpp)の読み取りは、最初の引数としてsplitaを取り、これを 2 つの sから範囲構築するものに渡します。SequenceSequenceT& Resultiter_splitboost::transform_iterator

SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;

std::stringしたがって、この型に必要なのは、逆参照(または技術的には BOOST_STRING_TYPENAME)を参照するイテレータのペアを受け取るコンストラクタを持つことだけです。.swap() メンバーを持ち、SequenceSequenceT::iterator型が.. の型を持ちますstd::string

証拠:

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <string>
#include <iterator>
#include <algorithm>
#include <iostream>
struct X
{
   typedef std::iterator<std::forward_iterator_tag,
           std::string, ptrdiff_t, std::string*, std::string&>
           iterator;
   X() {}
   template<typename Iter> X(Iter i1, Iter i2)
   {
       std::cout << "Constructed X: ";
       copy(i1, i2, std::ostream_iterator<std::string>(std::cout, " " ));
       std::cout << "\n";
   }
   void swap(X&) {}
};
int main()
{
  X x;
  boost::split(x, "a^b^c^", boost::is_any_of(std::string(1, '^')));
}

unordered_set<std::string>これらの要件も満たす必要があると思います。

于 2010-10-20T19:55:50.623 に答える