Boost C++ Libraries: Ticket #6978: Crash in rbtree_algorithms::rebalance_after_erasure, new in 1.49 https://svn.boost.org/trac10/ticket/6978 <p> The code below crashes with boost 1.49. </p> <p> This is because of a change in 1.49 to return references from node_traits::get* and take references as parameters to all tree algorithms. </p> <p> The code gets a reference to header.left with node_traits::get_left(header), and passes that reference into rbtree_algorithms::erase. </p> <p> tree_algorithms::erase does a node_traits::set_left(header, ...) at some point, and since z is a reference to header.left, the z pointer changes halfway through tree_algorithms::erase, and passing the wrong z pointer to rebalance_after_erasure after that causes the crash. </p> <pre class="wiki">#include &lt;iostream&gt; #include "boost/intrusive/options.hpp" #include "boost/intrusive/rbtree_algorithms.hpp" #include "boost/intrusive/rbtree.hpp" struct my_type : public boost::intrusive::set_base_hook&lt;&gt; { my_type(int i) : i_(i) {} int i_; }; typedef boost::intrusive::rbtree&lt;my_type&gt;::node_traits my_traits; struct Compare { bool operator()(my_traits::const_node_ptr a, my_traits::const_node_ptr b) { return static_cast&lt;const my_type*&gt;(a)-&gt;i_ &lt; static_cast&lt;const my_type*&gt;(b)-&gt;i_; } }; int main() { std::cout &lt;&lt; "if i wrap the pointer ref... " &lt;&lt; std::endl; { my_traits::node header; boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::init_header(&amp;header); for (int i = 0; i &lt; 20; ++i) boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::insert_equal(&amp;header, &amp;header, new my_type(i), Compare()); for (int i = 0; i &lt; 20; ++i) boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::erase(&amp;header, my_traits::node_ptr(my_traits::get_right(&amp;header))); } std::cout &lt;&lt; " OK!" &lt;&lt; std::endl; std::cout &lt;&lt; "if i don't wrap the pointer ref... " &lt;&lt; std::endl; { my_traits::node header; boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::init_header(&amp;header); for (int i = 100; i &lt; 120; ++i) boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::insert_equal(&amp;header, &amp;header, new my_type(i), Compare()); for (int i = 0; i &lt; 20; ++i) boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::insert_equal(&amp;header, &amp;header, new my_type(i), Compare()); for (int i = 0; i &lt; 20; ++i) boost::intrusive::rbtree_algorithms&lt;my_traits&gt;::erase(&amp;header, my_traits::get_left(&amp;header)); } std::cout &lt;&lt; " OK!" &lt;&lt; std::endl; // not really OK, it'll crash before it gets here return 0; } </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/6978 Trac 1.4.3 jeff-boosttrac@… Sat, 06 Oct 2012 15:31:47 GMT <link>https://svn.boost.org/trac10/ticket/6978#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6978#comment:1</guid> <description> <p> fixed by <a class="changeset" href="https://svn.boost.org/trac10/changeset/80512" title="Changed return types from reference to value due to subtle aliasing errors.">r80512</a>; broken again by <a class="changeset" href="https://svn.boost.org/trac10/changeset/80575" title="Applied pass by value to save copy constructors for pointers with ...">r80575</a>. </p> </description> <category>Ticket</category> </item> <item> <author>jeff-boosttrac@…</author> <pubDate>Sat, 06 Oct 2012 15:40:27 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6978#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6978#comment:2</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6978#comment:1" title="Comment 1">jeff-boosttrac@…</a>: </p> <blockquote class="citation"> <p> fixed by <a class="changeset" href="https://svn.boost.org/trac10/changeset/80512" title="Changed return types from reference to value due to subtle aliasing errors.">r80512</a>; broken again by <a class="changeset" href="https://svn.boost.org/trac10/changeset/80575" title="Applied pass by value to save copy constructors for pointers with ...">r80575</a>. </p> </blockquote> <p> Sorry - I must've got confused about what I was testing, <a class="changeset" href="https://svn.boost.org/trac10/changeset/80575" title="Applied pass by value to save copy constructors for pointers with ...">r80575</a> does not re-break it. Current trunk passes the test above, since <a class="changeset" href="https://svn.boost.org/trac10/changeset/80512" title="Changed return types from reference to value due to subtle aliasing errors.">r80512</a> </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Mon, 03 Dec 2012 17:15:09 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/6978#comment:3 https://svn.boost.org/trac10/ticket/6978#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> Thanks for the report. Closing the issue as it's fixed in Boost 1.52 </p> Ticket