Boost C++ Libraries: Ticket #7015: boost::signals::connection with shared_ptr to connected signal https://svn.boost.org/trac10/ticket/7015 <p> If you create a connection with a shared_ptr that controls the lifespan of the signal an access violation occurs on disconnection if that is the last remaining reference to the object. </p> <div class="wiki-code"><div class="code"><pre><span class="k">class</span> <span class="nc">Child</span> <span class="o">:</span> <span class="k">public</span> <span class="n">boost</span><span class="o">::</span><span class="n">signals</span><span class="o">::</span><span class="n">trackable</span> <span class="p">{</span> <span class="k">public</span><span class="o">:</span> <span class="n">Child</span><span class="p">(){}</span> <span class="k">virtual</span> <span class="o">~</span><span class="n">Child</span><span class="p">(){}</span> <span class="kt">void</span> <span class="n">callback</span><span class="p">(</span> <span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span> <span class="p">)</span> <span class="p">{</span> <span class="n">printf</span><span class="p">(</span> <span class="s">&quot;Child::callback( %d, %d )</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="p">);</span> <span class="p">}</span> <span class="n">boost</span><span class="o">::</span><span class="n">signal</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="o">&gt;</span> <span class="n">mSignal</span><span class="p">;</span> <span class="p">};</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span> <span class="p">{</span> <span class="n">boost</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Child</span><span class="o">&gt;</span> <span class="n">c</span><span class="p">(</span> <span class="k">new</span> <span class="n">Child</span> <span class="p">);</span> <span class="n">boost</span><span class="o">::</span><span class="n">signals</span><span class="o">::</span><span class="n">connection</span> <span class="n">con</span><span class="p">;</span> <span class="n">con</span> <span class="o">=</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">mSignal</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span> <span class="n">boost</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span> <span class="o">&amp;</span><span class="n">Child</span><span class="o">::</span><span class="n">callback</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">_1</span> <span class="p">)</span> <span class="p">);</span> <span class="n">c</span><span class="o">-&gt;</span><span class="n">mSignal</span><span class="p">(</span> <span class="mi">5</span> <span class="p">);</span> <span class="n">c</span><span class="p">.</span><span class="n">reset</span><span class="p">();</span> <span class="c1">// The connection is the only thing keeping it alive. When we disconnect</span> <span class="c1">// it will also destroy the signal. This causes a memory access violation</span> <span class="c1">// when the signal containing the list of connections gets deleted while</span> <span class="c1">// removing an item from that list.</span> <span class="n">con</span><span class="p">.</span><span class="n">disconnect</span><span class="p">();</span> <span class="p">}</span> </pre></div></div><p> The fix is to prevent the slot from going out of scope during the act of disconnecting from the signal. </p> <pre class="wiki">diff --git a/libs/signals/src/signal_base.cpp b/libs/signals/src/signal_base.cpp index 759672d..918e811 100644 --- a/libs/signals/src/signal_base.cpp +++ b/libs/signals/src/signal_base.cpp @@ -143,8 +143,14 @@ namespace boost { self-&gt;flags.delayed_disconnect = true; } else { // Just remove the slot now, it's safe + // There is a chance that the binding has the last reference to + // the signal, and destroying it will destroy the signal. To prevent + // this from causing a problem keep a local copy of the binding + // during it's removal from the slot list. + boost::any keep_alive = (*slot)-&gt;second; self-&gt;slots_.erase(*slot); + return; } } } </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/7015 Trac 1.4.3 Nick Mayer <nick.mayer@…> Fri, 22 Jun 2012 15:44:07 GMT attachment set https://svn.boost.org/trac10/ticket/7015 https://svn.boost.org/trac10/ticket/7015 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">signal_base.patch</span> </li> </ul> <p> Patch in the description of the issue </p> Ticket anonymous Wed, 15 Aug 2012 20:12:25 GMT <link>https://svn.boost.org/trac10/ticket/7015#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/7015#comment:1</guid> <description> <p> Any ideas on what would need to be done to get this patch accepted? </p> </description> <category>Ticket</category> </item> </channel> </rss>