传递boost :: unordered_set作为结果映射以升级:: split
-
09-10-2019 - |
题
有人知道是否将Boost :: unordered_set作为Boost :: Split的第一个参数是犹太洁食?在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的Coredumps,尽管它似乎是根据时机而变化的):
==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挤压盒子;这是我的相关系统信息:
$ 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 ::通过传递无法处理序列的容器来拆分?谢谢!
解决方案
在Boost用户邮件列表中确认这是Boost :: Unordered_set实现中的错误。邮件列表上有一个补丁程序,很快就会检查一个修复程序,希望能及时以Boost 1.45进行检查。
感谢大家研究这个!
其他提示
我认为答案应该是的。
阅读标题(split.hpp
和 iter_find.hpp
) split
服用 SequenceSequenceT& Result
作为第一个论点,它传达给 iter_split
哪个范围从两个 boost::transform_iterator
S:
SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;
因此,这种类型的所有需求是它具有一个构造函数,该构造函数采用一对迭代器,将其解释为 std::string
(或从技术上讲,要bost_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>
也应该满足这些要求。
显然,答案是 不 是的.
使用以下代码,我在该代码上获得编译时警告和一个运行时断言(Visual C ++ V10) unordered_set
而 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
)和目标容器是问题。我会发布警告错误,但这是那些“战与和平”模板警告之一。
编辑:
这看起来像是提升的错误 unordered_set
?当我使用以下内容时,它会按照您的期望工作:
std::unordered_set<std::string> tags_set_std;
boost::split( tags_set_std, string("a^b^c^"), boost::is_any_of(string("^")) );