Boost C++ Libraries: Ticket #3658: Remove dependency on static initialization/destruction order https://svn.boost.org/trac10/ticket/3658 <p> The static_holder depends on the static initialization/destruction order, as it is implemented as a function-local static variable. If there are flyweights in the static or global variables, which are initialized lazilly, the flyweight value may get destroyed before the flyweights that refer to it. For example: </p> <pre class="wiki">#include &lt;iostream&gt; #include &lt;string&gt; #include &lt;boost/shared_ptr.hpp&gt; #include &lt;boost/flyweight.hpp&gt; #include &lt;boost/flyweight/key_value.hpp&gt; struct A { int m_n; A(int n) : m_n(n) { std::cout &lt;&lt; "A()" &lt;&lt; std::endl; } ~A() { std::cout &lt;&lt; "~A()" &lt;&lt; std::endl; } bool operator== (A const&amp; a) const { return m_n == a.m_n; } friend std::size_t hash_value(A const&amp; a) { return a.m_n; } }; struct B { boost::flyweight&lt; boost::flyweights::key_value&lt; int, A &gt; &gt; m_A; B() : m_A(10) { std::cout &lt;&lt; "B()" &lt;&lt; std::endl; } ~B() { std::cout &lt;&lt; "~B()" &lt;&lt; std::endl; } }; boost::shared_ptr&lt; B &gt; p; int main(int, char*[]) { p.reset(new B()); return 0; } </pre><p> Compiled with MSVC: </p> <pre class="wiki">cl -Ox -MD -EHsc -I . -DNDEBUG ./flyweight_test.cpp </pre><p> Produces: </p> <pre class="wiki">A() B() ~A() ~B() </pre><p> And a crash. </p> <p> A possible solution would be to destroy flyweight values only when reference counter from flyweights drops to zero. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3658 Trac 1.4.3 Joaquín M López Muñoz Fri, 27 Nov 2009 09:21:39 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/3658#comment:1 https://svn.boost.org/trac10/ticket/3658#comment:1 <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">invalid</span> </li> </ul> <p> The issue is a known limitation of static_holder that can't be dealt with in a more satisfactory manner than its current implementation. The solution requires some user help, as explained in </p> <p> <a href="http://www.boost.org/libs/flyweight/doc/tutorial/technical.html#static_init">http://www.boost.org/libs/flyweight/doc/tutorial/technical.html#static_init</a> </p> <p> In your particular case, add the following before the line where p is declared: </p> <pre class="wiki">static boost::flyweight&lt; boost::flyweights::key_value&lt; int, A &gt; &gt;::initializer fwinit; boost::shared_ptr&lt; B &gt; p; </pre> Ticket Andrey Semashev Fri, 27 Nov 2009 18:32:07 GMT status changed; resolution deleted https://svn.boost.org/trac10/ticket/3658#comment:2 https://svn.boost.org/trac10/ticket/3658#comment:2 <ul> <li><strong>status</strong> <span class="trac-field-old">closed</span> → <span class="trac-field-new">reopened</span> </li> <li><strong>resolution</strong> <span class="trac-field-deleted">invalid</span> </li> </ul> <p> That solution is not suitable for me because p and B and A are rather distant (they belong to different components of the application). In fact, the component that creates p doesn't know anything about A's implementation, and about flyweights in particular. </p> <p> Why is it not possible to implement a fair reference counted semantics? </p> <p> I reopen the ticket as I feel that this problem is not solved yet. This may not be a coding bug, but I believe this is a major design flaw that deserves to be addressed. If you have any objections or suggestions, we may discuss it either here or on the dev. ML. </p> Ticket Joaquín M López Muñoz Sat, 28 Nov 2009 11:09:52 GMT <link>https://svn.boost.org/trac10/ticket/3658#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3658#comment:3</guid> <description> <p> Yes, please bring this to the mailing list so that we can discuss it in a more fluent manner. Thank you! </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrey Semashev</dc:creator> <pubDate>Sat, 28 Nov 2009 13:26:21 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3658#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3658#comment:4</guid> <description> <p> <a class="ext-link" href="http://thread.gmane.org/gmane.comp.lib.boost.devel/197102"><span class="icon">​</span>Done</a>. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Joaquín M López Muñoz</dc:creator> <pubDate>Fri, 13 Jan 2012 08:02:51 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/3658#comment:5 https://svn.boost.org/trac10/ticket/3658#comment:5 <ul> <li><strong>status</strong> <span class="trac-field-old">reopened</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> I'm re-closing this old one, as the suggestions on the mailing list discussion seem to me too cumbersome to implement, and basically break the orthogonality of the different concepts (factory, holder, values.) As suggested there, you can define your own holder that basically does not delete the factory, at the cost of a memory leak (if it can be called a leak, as this is not your normal leak where memory usage increases over time, which is the problematic case.) </p> Ticket