zu verstärken, um einen boost :: unordered_set als Ergebnis Karte Passing :: Split
-
09-10-2019 - |
Frage
Wer weiß, wenn es koscher einen Schub passieren :: unordered_set als ersten Parameter an boost :: Split? Unter libboost1.42-dev scheint diese Probleme zu verursachen. Hier ist ein kleines Beispiel-Programm, das das Problem verursacht, nennt es 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;
}
Dann, wenn ich die folgenden Befehle ausführen:
g++ -o test-split test-split.cc; valgrind ./test-split
ich eine Reihe von Beschwerden in valgrind wie die eine, die folgt (ich manchmal auch coredumps ohne valgrind sehen, obwohl es basierend auf Timing zu variieren scheint):
==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)
Dies ist eine Debian Squeeze-Box; hier ist mein relevantes Systeminfo:
$ 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
Allerdings ist der Code scheint zu funktionieren, wenn ich Herabstufung libboost1.42-dev auf libboost1.40-dev. Das ist also ein Fehler im Boost 1,42, oder bin ich zu mißbrauchen boost :: Spaltung von in einem Behälter vorbei, die nicht Sequenzen verarbeiten können? Dank!
Lösung
Dies wurde auf dem Boost-Benutzer bestätigt Mailing-Liste ein Fehler in der Verstärkung sein :: unordered_set Umsetzung. Es gibt einen Patch zur Verfügung auf der Mailingliste und ein Update wird in Kürze überprüft werden, hoffentlich rechtzeitig für Schub 1,45.
Vielen Dank aller für in diesen suchen!
Andere Tipps
Ich denke, die Antwort sollte ja sein.
Lesen der Header (split.hpp
und iter_find.hpp
) split
nimmt einen SequenceSequenceT& Result
als erstes Argument, das es iter_split
gibt die Entfernungs-Konstrukte aus zwei boost::transform_iterator
s:
SequenceSequenceT Tmp(itBegin, itEnd);
Result.swap(Tmp);
return Result;
Also alles braucht es von dieser Art ist, dass es einen Konstruktor hat, der ein Paar von Iteratoren, die dereferenzieren zu std::string
nimmt (oder technisch zu BOOST_STRING_TYPENAME). Und hat eine .swap () Mitglied .. und hat einen SequenceSequenceT::iterator
Typ, dessen Typ std::string
.
Beweis:
#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, '^')));
}
ich denke, dass unordered_set<std::string>
diese Anforderungen auch erfüllen sollte.
Offensichtlich ist die Antwort no Ja .
Mit dem folgenden Code, erhalte ich Kompilierung-Warnungen und eine Runtime-assert (Visual C ++ v10) auf dem unordered_set
während der vector
funktionieren gut (abgesehen von einer leeren Zeichenfolge in dem letzten Elemente, aufgrund des nachlauf ‚^‘) .
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("^") );
Iterator Kompatibilität zwischen Quelle (string
) und dem Zielcontainer ist das Problem. Ich würde die Warnung Fehler schreiben, aber es ist eines dieser „Krieg und Frieden“ Template Warnungen.
EDIT:
Das sieht wie ein Fehler in Boost-unordered_set
? Wenn ich die folgenden verwenden, funktioniert es wie erwartet:
std::unordered_set<std::string> tags_set_std;
boost::split( tags_set_std, string("a^b^c^"), boost::is_any_of(string("^")) );