@@ -122,35 +122,59 @@ class remove_elements_to_reinsert
122122 >::type sorted_elements_type;
123123
124124 sorted_elements_type sorted_elements;
125- // If constructor is used instead of resize() MS implementation leaks here
126- sorted_elements.reserve (elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
127125
128- for ( typename elements_type::const_iterator it = elements.begin () ;
129- it != elements.end () ; ++it )
126+ BOOST_TRY
130127 {
131- point_type element_center;
132- geometry::centroid (rtree::element_indexable (*it, translator), element_center,
133- strategy);
134- sorted_elements.push_back (std::make_pair (
135- comparable_distance_pp::call (node_center, element_center, strategy),
136- *it)); // MAY THROW (V, E: copy)
137- }
128+ // If constructor is used instead of resize() MS implementation leaks here
129+ sorted_elements.reserve (elements_count); // MAY THROW, STRONG (alloc)
138130
139- // sort elements by distances from center
140- std::partial_sort (
141- sorted_elements.begin (),
142- sorted_elements.begin () + reinserted_elements_count,
143- sorted_elements.end (),
144- distances_dsc<comparable_distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)
145-
146- // copy elements which will be reinserted
147- result_elements.clear ();
148- result_elements.reserve (reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
149- for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin () ;
150- it != sorted_elements.begin () + reinserted_elements_count ; ++it )
131+ for ( typename elements_type::const_iterator it = elements.begin () ;
132+ it != elements.end () ; ++it )
133+ {
134+ point_type element_center;
135+ geometry::centroid (rtree::element_indexable (*it, translator), element_center,
136+ strategy);
137+ sorted_elements.push_back (std::make_pair (
138+ comparable_distance_pp::call (node_center, element_center, strategy),
139+ *it)); // MAY THROW (V, E: copy)
140+ }
141+
142+ // sort elements by distances from center
143+ std::partial_sort (
144+ sorted_elements.begin (),
145+ sorted_elements.begin () + reinserted_elements_count,
146+ sorted_elements.end (),
147+ distances_dsc<comparable_distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)
148+
149+ // copy elements which will be reinserted
150+ result_elements.clear ();
151+ result_elements.reserve (reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
152+ for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin () ;
153+ it != sorted_elements.begin () + reinserted_elements_count ; ++it )
154+ {
155+ result_elements.push_back (it->second ); // MAY THROW (V, E: copy)
156+ }
157+ }
158+ BOOST_CATCH (...)
151159 {
152- result_elements.push_back (it->second ); // MAY THROW (V, E: copy)
160+ // NOTE: This code is here to prevent leaving the node in overflow state
161+ // (with more than max elements) after an exception is thrown during the
162+ // preparation of elements for reinsertion (#1399). At this point the node
163+ // has not been modified yet and still contains exactly max+1 elements
164+ // (one push_back triggered the overflow handling).
165+ // Remove the overflow element to restore the node invariant, matching
166+ // the behavior of the split exception handler.
167+ result_elements.clear ();
168+
169+ if (elements.size () > parameters.get_max_elements ())
170+ {
171+ destroy_element<MembersHolder>::apply (elements.back (), allocators);
172+ elements.pop_back ();
173+ }
174+
175+ BOOST_RETHROW
153176 }
177+ BOOST_CATCH_END
154178
155179 BOOST_TRY
156180 {
0 commit comments