[Multi-Index] crash on iterator copy or assignment
Hi, I've been using B.MI for a few days, and until now it's worked great for me. I've included below in Exhibit A a simplified (and a bit obfuscated, sorry) version of what I've been using (a proxy, indexed by name and type, and a method returning all instances of a given type). Filling in a list of all entries matching a given type (in exhibit A) works great. But now I was trying to return a custom (non-standard) iterator, where the client gets a pointer to a abstract base iterator (allows to hide the B.MI stuff in the concrete derived iterator), wrapped in an auto_ptr. The private concrete iterator internally stores the B.MI iterator from the index I'm interested in (exhibit B). This compiles (vs2005 sp1 on winXP 32), but it crashes at runtime on the call to boost::tie, during iterator assignment apparently. (call stack in exhibit C). So at this point I have no clue what's going on, and I would appreciate some help. The level of template complexity is more than stretching my abilities I'm afraid, just reading the type names makes my end spin ;) We're going to try it using GCC on Linux to see if it might be a compiler issue, and possibly try vs2008 as well, but if anyone knows if taking copies of the iterators is allowed (I know the index themselves shouldn't be copied, and we don't), and if yes why it's failing in this particular case, I'd appreciate. Thanks, --DD PS: Earlier I had a version of ByTypeFooIterator that took the begin/end iterator as param to its Ctor, taking a *copy*, but that also crashed w/o a stack trace this time. PPS: What I was trying to test in fact was whether I could get two equal ranges for two different MyTypeInfo, and iterate on those but interleaving the calls to ++iter, to verify nested or interleaved iteration was valid with B.MI. But I never reached that point. === Exhibit A: the code that works === struct FooProxy { Foo*const foo_; FooProxy(Foo* foo) : foo_(foo) {} const MyString& get_name() const { return foo_->name(); } const MyTypeInfo& get_type() const { return foo_->type_info(); } }; struct ByName {}; struct ByType {}; typedef boost::multi_index_container< FooProxy , indexed_by< hashed_non_unique< tag<ByName>, BOOST_MULTI_INDEX_CONST_MEM_FUN( FooProxy , const MyString&, get_name ) >, hashed_non_unique< tag<ByType>, BOOST_MULTI_INDEX_CONST_MEM_FUN( FooProxy , const MyTypeInfo&, get_type ) >
FooIndex;
FooIndex foo_index_;
typedef FooIndex::index<ByName>::type FoosByName;
typedef FooIndex::index<ByType>::type FoosByType;
size_t select_foos(const MyTypeInfo& tinfo, MyList
my_lib.dll!std::_Iterator_base::operator=(const std::_Iterator_base & _Right={...}) Line 374 + 0x8 bytes C++
my_lib.dll!std::iterator ,boost::multi_index::detail::bucket_array my_lib.dll!boost::incrementable ,boost::multi_index::detail::bucket_array my_lib.dll!boost::equality_comparable1 ,boost::multi_index::detail::bucket_array my_lib.dll!boost::input_iteratable ,boost::multi_index::detail::bucket_array my_lib.dll!boost::forward_iteratable ,boost::multi_index::detail::bucket_array my_lib.dll!boost::forward_iterator_helper ,boost::multi_index::detail::bucket_array my_lib.dll!boost::multi_index::detail::hashed_index_iterator ,boost::multi_index::detail::bucket_array my_lib.dll!boost::tuples::tuple ,boost::multi_index::detail::bucket_array my_lib.dll!iterate(const MyTypeInfo & tinfo={...}) Line 510 +
0x51 bytes C++
AMDG Dominique Devienne wrote:
I've been using B.MI for a few days, and until now it's worked great for me. I've included below in Exhibit A a simplified (and a bit obfuscated, sorry) version of what I've been using (a proxy, indexed by name and type, and a method returning all instances of a given type).
Filling in a list of all entries matching a given type (in exhibit A) works great.
But now I was trying to return a custom (non-standard) iterator, where the client gets a pointer to a abstract base iterator (allows to hide the B.MI stuff in the concrete derived iterator), wrapped in an auto_ptr. The private concrete iterator internally stores the B.MI iterator from the index I'm interested in (exhibit B). This compiles (vs2005 sp1 on winXP 32), but it crashes at runtime on the call to boost::tie, during iterator assignment apparently. (call stack in exhibit C).
After filling in enough to make your code compile, it works for me. I've attached what I did. If this works for you, can you post a minimal and complete example that fails? In Christ, Steven Watanabe
On Thu, Mar 12, 2009 at 3:36 PM, Steven Watanabe
After filling in enough to make your code compile, it works for me. I've attached what I did. If this works for you, can you post a minimal and complete example that fails?
Hi Steven, Your example works for me as well, since you've found the same fix my colleague found, which is to write std::auto_ptr<ByTypeFooIterator> iter_ptr(new ByTypeFooIterator); instead of std::auto_ptr<ByTypeFooIterator> iter_ptr = new ByTypeFooIterator; This one change was "all" it took (except I couldn't see it of course...) Thank you very much for taking the time to test it Steven, and for finding a solution. Cheers again, --DD
On Thu, Mar 12, 2009 at 1:50 PM, Dominique Devienne
// public method std::auto_ptr<FooIterator> iterate(const MyTypeInfo& tinfo) { FoosByType& by_type = get<ByType>(foo_index_);
std::auto_ptr<ByTypeFooIterator > iter_ptr = new ByTypeFooIterator;
A colleague found the culprit above, thanks to a GCC warning on the above line. Using the "construction" assignment, which I assumed would call the auto_ptr(T*) Ctor, was in fact calling auto_ptr_ref(void*) and then auto_ptr(auto_ptr_ref&), leading to the crash in tie on the next line. (there must be a bug in vs2005 std lib here...) Changing this to iter_ptr(new ByTypeFooIterator); forced the use of auto_ptr(T*) and the whole unit test worked like a charm ;-)
boost::tie(iter_ptr->cur_, iter_ptr->end_) = by_type.equal_range(tinfo); return iter_ptr; }
Note that I could then do my "interleaving" test, and this also worked the first time. Boost Multi-Index is simply a gem! Thanks so much for it. Cheers, --DD
participants (2)
-
Dominique Devienne
-
Steven Watanabe