[boost-users][Multi-Index] crash in equal_range()

Hello, I've got a multi_index_container with few indices, as follows: struct Record { // some data }; typedef mi::multi_index_container< Record, mi::indexed_by< mi::ordered_non_unique<mi::tag<Record::stream>, mi::member<Record, int, &Record::streamID_> >, mi::ordered_non_unique<mi::tag<Record::setting>, mi::member<Record, int, &Record::settingID_> >
Records;
typedef Records::index<Record::stream>::type RecordsByStream; typedef Records::index<Record::setting>::type RecordsBySetting; Records records_; Then I insert 1 Record into records_. Later in the code I do the following lookup: RecordsBySetting bySetting = records_.get<Record::setting>(); std::pair<RecordsBySetting::iterator, RecordsBySetting::iterator> sameSetting = bySetting.equal_range(1); // record with setting id == 1 exists in the container! In the last line, in equal_range() I've got an exception (access violation). Am I doing something wrong? Any help would be greatly appreciated! Some tracing: The crash is in ordered_index::equal_range(const CompatibleKey& x) in its 1st line: std::pair<node_type*,node_type*> p= ordered_index_equal_range(root(),header(),key,x,comp); An attepmt to access the root() fails. Here is the call stack: SomeProg.exe!boost::multi_index::detail::ordered_index_node_compressed_base<std::allocator<void>
::parent_ref::operator boost::multi_index::detail::ordered_index_node_impl<std::allocator<void> *() Line 161 + 0x5 bytes C++ SomeProg.exe!boost::multi_index::detail::ordered_index<boost::multi_index::member<Record,int,8>,std::less<int>,boost::multi_index::detail::nth_layer<2,Record,boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::tag<Record::streamable,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::member<Record,int,4>,boost::mpl::na>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<Record::setting,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::member<Record,int,8>,boost::mpl::na>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<Record> ,boost::mpl::vector1<Record::setting>,boost::multi_index::detail::ordered_non_unique_tag>::root() Line 879 + 0x40 bytes C++ SomeProg.exe!boost::multi_index::detail::ordered_index<boost::multi_index::member<Record,int,8>,std::less<int>,boost::multi_index::detail::nth_layer<2,Record,boost::multi_index::indexed_by<boost::multi_index::ordered_non_unique<boost::multi_index::tag<Record::streamable,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::member<Record,int,4>,boost::mpl::na>,boost::multi_index::ordered_non_unique<boost::multi_index::tag<Record::setting,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::member<Record,int,8>,boost::mpl::na>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<Record> ,boost::mpl::vector1<Record::setting>,boost::multi_index::detail::ordered_non_unique_tag>::equal_range<int>(const int & x=1) Line 493 + 0x20 bytes C++

Well, I think I've realised what happed there:
RecordsBySetting bySetting = records_.get<Record::setting>();
The index is copied there, and the copy is in invalid state for some reason. However, if take the reference, everything goes well: RecordsBySetting &bySetting = records_.get<Record::setting>(); 2008/7/7, Igor R <boost.lists@gmail.com>:
Hello,
I've got a multi_index_container with few indices, as follows:
struct Record { // some data };
typedef mi::multi_index_container< Record, mi::indexed_by< mi::ordered_non_unique<mi::tag<Record::stream>, mi::member<Record, int, &Record::streamID_> >, mi::ordered_non_unique<mi::tag<Record::setting>, mi::member<Record, int, &Record::settingID_> >
Records;
typedef Records::index<Record::stream>::type RecordsByStream; typedef Records::index<Record::setting>::type RecordsBySetting;
Records records_;
Then I insert 1 Record into records_. Later in the code I do the following lookup:
RecordsBySetting bySetting = records_.get<Record::setting>(); std::pair<RecordsBySetting::iterator, RecordsBySetting::iterator> sameSetting = bySetting.equal_range(1); // record with setting id == 1 exists in the container!

________________________________________ De: boost-users-bounces@lists.boost.org [boost-users-bounces@lists.boost.org] En nombre de Igor R [boost.lists@gmail.com] Enviado el: lunes, 07 de julio de 2008 16:53 Para: boost-users@lists.boost.org Asunto: Re: [Boost-users] [boost-users][Multi-Index] crash in equal_range()
Well, I think I've realised what happed there:
RecordsBySetting bySetting = records_.get<Record::setting>();
The index is copied there, and the copy is in invalid state for some reason. However, if take the reference, everything goes well:
RecordsBySetting &bySetting = records_.get<Record::setting>();
Hi Igor, Correct, the problem was exactly as you said: indices are not meant to be copied and can only be referred to to via references (or pointers). You might legitimately ask: why haven't you made their copy ctors private/protected so as to avoid this kind of errors? Well, the copy ctors are indeed protecetd except for those *defective* compilers for which the Boost.Config macro BOOST_NO_MEMBER_TEMPLATE_FRIENDS is set, among which are MSVC 8.0 and older (which I guess include the one you're using). This issue gets reported every so often, see for instance an older post about it: http://lists.boost.org/boost-users/2005/02/10055.php To try to prevent new users from keep falling into the same trap I added some warning text at the last paragraph of http://www.boost.org/libs/multi_index/doc/tutorial/basics.html#multiple_sort Unfortunately, the caveat seems not to be conspicuous enough, judging from the number of times this problem has been reported. I'm sorry it also hit you, hope your further experience with B.MI is more pleasant. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Oh, I see... Thank you for this clarification! I didn't know that VC8.0 has such an issue.
Well, the copy ctors are indeed protecetd except for those *defective* compilers for which the Boost.Config macro BOOST_NO_MEMBER_TEMPLATE_FRIENDS is set, among which are MSVC 8.0 and older (which I guess include the one you're using).
participants (2)
-
Igor R
-
JOAQUIN M. LOPEZ MUÑOZ