Boost C++ Libraries: Ticket #3950: boost::interprocess::mapped_region destructor deletes shm where it shouldn't. https://svn.boost.org/trac10/ticket/3950 <p> Hello, </p> <p> I have troubles with the following piece of code: </p> <pre class="wiki">#include &lt;cstdlib&gt; #include &lt;boost/interprocess/anonymous_shared_memory.hpp&gt; #include &lt;boost/interprocess/mapped_region.hpp&gt; int main() { boost::interprocess::mapped_region aRegion( boost::interprocess::anonymous_shared_memory( sizeof( int ) ) ); *(int *)aRegion.get_address() = 0x33; return EXIT_SUCCESS; } </pre><p> It should create an anonymous memory region and writes an int in it. </p> <p> Whereas this piece of code works when compiled with gcc without optimizations, when it is compiled with -O2 or -O3 with gcc 4.4.3, it produces a segmentation fault. </p> <p> strace and gdb show that the shared memory is mmapped and unmapped before the assignment is done. (Whereas when the code is compiled without optimization, the shared memory is clearly mapped, then the assignement is done, then it is unmapped.) </p> <p> My understanding of what happens is that: </p> <ul><li>the anonymous_shared_memory() function calls raw_mapped_region_creator::create_posix_mapped_region which creates a local mapped_region object. </li><li>This mapped_region object is non-copyable, but movable. </li></ul><p> When the return statement for that local object is called, it invokes mapped_region::mapped_region(BOOST_INTERPROCESS_RV_REF(mapped_region) other) which: </p> <ul><li>create the returned object as invalid, </li><li>swap the content of the local object with the one of the "invalid initialized" returned object. </li></ul><p> Thanks to this, the returned object has the proper values and the local object is set as "invalid" just before its destructor is called so that the shm won't be unmapped at raw_mapped_region_creator::create_posix_mapped_region and anonymous_shared_memory exit. </p> <p> For a reason I don't understand, I have the feeling that, when the code is compiled with gcc 4.4.3 -O2 or -O3, this "swap with invalid mapped_region" mechanism is zapped out so that the shm mmapped at the beginning of anonymous_shared_memory is unmapped by ~mapped_region when this function returns. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3950 Trac 1.4.3 Lénaïc Huard <lhuard@…> Wed, 24 Feb 2010 22:27:02 GMT <link>https://svn.boost.org/trac10/ticket/3950#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:1</guid> <description> <p> The issue <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3951" title="#3951: Bugs: assertion failed calling find&lt;&gt; in managed_shared_memory (might be a ... (closed: fixed)">#3951</a> is very very similar to this one. </p> <p> Like in this ticket, I strongly suspect a bug in latest gcc which optimizations break something in the tricks emulating Rvalue references. Both issues disappear when the code samples are compiled with latest gcc and -std=c++0x or -std=gnu++0x in which case, the Rvalue references are managed by the compiler and the boost tricks become useless. </p> </description> <category>Ticket</category> </item> <item> <author>Lénaïc Huard <lhuard@…></author> <pubDate>Fri, 21 May 2010 19:40:18 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/3950 https://svn.boost.org/trac10/ticket/3950 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_interprocess.patch</span> </li> </ul> Ticket Lénaïc Huard <lhuard@…> Fri, 21 May 2010 20:07:32 GMT <link>https://svn.boost.org/trac10/ticket/3950#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:2</guid> <description> <p> I found the problem. </p> <p> The problem was indeed caused by the strict aliasing rule violation by the class rv (in detail/move.hpp) </p> <p> The case described here above and in <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3951" title="#3951: Bugs: assertion failed calling find&lt;&gt; in managed_shared_memory (might be a ... (closed: fixed)">#3951</a> can be solved by flagging the class rv with the gcc specific <code>__attribute__((__may_alias__))</code>. </p> <p> The full patch that fixes the issue is attached in <a class="ext-link" href="https://svn.boost.org/trac/boost/raw-attachment/ticket/3950/boost_interprocess.patch"><span class="icon">​</span>boost_interprocess.patch</a>. </p> <p> Could you please have a look at it? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Fri, 21 May 2010 21:15:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:3</guid> <description> <p> Thanks! What if you modify move.hpp to modify all reinterpret_cast with static_cast? Does this also solve the problem? </p> </description> <category>Ticket</category> </item> <item> <author>Lénaïc Huard <lhuard@…></author> <pubDate>Fri, 21 May 2010 22:10:56 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:4</guid> <description> <p> I tried to replace all the <code>reinterpret_cast</code> by <code>static_cast</code> but it doesn't help to solve the issue. </p> <p> According to what I've read <a class="ext-link" href="http://stackoverflow.com/questions/1225741/performance-impact-of-fno-strict-aliasing"><span class="icon">​</span>here</a>: </p> <blockquote> <p> GCC is fairly aggressive about it: enabling strict aliasing will cause it to think that pointers that are "obviously" equivalent to a human (as in, foo* a; bar * b; b = (foo*)a;) cannot alias, which allows for some very aggressive transformations, but can obviously break non-carefully written code. </p> </blockquote> <p> If <code>rv</code> references alias to references to other "supposed incompatible" types, GCC will assume that operations on the first reference cannot affect the object pointed to by the second reference. In nearly all cases. Hence the issue. </p> <p> The code example of this issue doesn't raise any warning. But the one of <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/3951" title="#3951: Bugs: assertion failed calling find&lt;&gt; in managed_shared_memory (might be a ... (closed: fixed)">#3951</a> raises: </p> <pre class="wiki">/home/lenaic/doc/prog/boost-trunk/boost/interprocess/sync/scoped_lock.hpp:348: warning: dereferencing pointer ‘&lt;anonymous&gt;’ does break strict-aliasing rules /home/lenaic/doc/prog/boost-trunk/boost/interprocess/sync/scoped_lock.hpp:347: warning: dereferencing pointer ‘&lt;anonymous&gt;’ does break strict-aliasing rules /home/lenaic/doc/prog/boost-trunk/boost/interprocess/segment_manager.hpp:1334: note: initialized from here </pre><p> And those warnings are well removed by the addition of <code>__attribute__((__may_alias__))</code> on <code>rv</code>. </p> <p> By the way, in the patch I provided, I'm still wondering why I had to touch <code>mapped_region.hpp</code>. But without moving those two methods definition to their declaration, I get this unbelievable error: </p> <pre class="wiki">/home/lenaic/doc/prog/boost-trunk/boost/interprocess/mapped_region.hpp:381: error: prototype for ‘boost::interprocess::mapped_region::mapped_region(boost::interprocess::rv&lt;boost::interprocess::mapped_region&gt;&amp;)’ does not match any in class ‘boost::interprocess::mapped_region’ /home/lenaic/doc/prog/boost-trunk/boost/interprocess/mapped_region.hpp:84: error: candidates are: boost::interprocess::mapped_region::mapped_region(boost::interprocess::rv&lt;boost::interprocess::mapped_region&gt;&amp;) [...] </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Fri, 21 May 2010 22:55:00 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:5</guid> <description> <p> Many thanks, I wouldn't be able to fix it by myself, I thought downcasted classes would not break strict aliasing but I was wrong. </p> </description> <category>Ticket</category> </item> <item> <author>Lénaïc Huard <lhuard@…></author> <pubDate>Fri, 21 May 2010 23:20:48 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:6</guid> <description> <p> You're welcome! </p> <p> I'm not a strict aliasing rules expert. Maybe is it gcc which is wrong and which performs optimizations that are even more aggressive than what the standard allows. I'm not able to say. </p> </description> <category>Ticket</category> </item> <item> <author>kab@…</author> <pubDate>Sun, 23 May 2010 01:30:56 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:7</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3950#comment:5" title="Comment 5">igaztanaga</a>: </p> <blockquote class="citation"> <p> Many thanks, I wouldn't be able to fix it by myself, I thought downcasted classes would not break strict aliasing but I was wrong. </p> </blockquote> <p> A downward static_cast should be fine, so long as the object is in fact of the type being downcasted to. See C++03 5.2.9/5. If gcc strict aliasing optimizations are breaking that, that would be very bad. </p> </description> <category>Ticket</category> </item> <item> <author>kab@…</author> <pubDate>Sun, 23 May 2010 01:34:24 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:8</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3950#comment:7" title="Comment 7">kab@…</a>: </p> <blockquote class="citation"> <p> See C++03 5.2.9/5. </p> </blockquote> <p> Pointers are probably involved in this discussion, in which case the correct reference is C++03 5.2.9/8. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Sun, 23 May 2010 07:51:49 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:9</guid> <description> <p> I think GCC is right, because the dynamic type of the object is not rv&lt;T&gt; but T. We don't create any rv&lt;T&gt; object so downcasting T to a non-existent rv&lt;T&gt; object is at least doubtful. The standard says: </p> <p> INCITS+ISO+IEC+14882-2003 C++03 standard. </p> <p> 3.10 Lvalues and rvalues / 15 </p> <p> If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined48): </p> <ul><li>the dynamic type of the object, </li><li>a cv-qualified version of the dynamic type of the object, </li><li>a type that is the signed or unsigned type corresponding to the </li></ul><p> dynamic type of the object, </p> <ul><li>a type that is the signed or unsigned type corresponding to a cv- </li></ul><p> qualified version of the dynamic type of the object, </p> <ul><li>an aggregate or union type that includes one of the aforementioned </li></ul><p> types among its members (including, recursively, a member of a subaggregate or contained union), </p> <ul><li>a type that is a (possibly cv-qualified) base class type of the </li></ul><p> dynamic type of the object, </p> <ul><li>a char or unsigned char type. </li></ul><p> rv&lt;T&gt; is a class, but not an aggregate class, since (8.5.1 Aggregates [dcl.init.aggr] p.2): </p> <p> An aggregate class is a class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions. </p> </description> <category>Ticket</category> </item> <item> <author>kab@…</author> <pubDate>Sun, 23 May 2010 09:53:51 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3950#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3950#comment:10</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/3950#comment:9" title="Comment 9">igaztanaga</a>: </p> <blockquote class="citation"> <p> I think GCC is right, because the dynamic type of the object is not rv&lt;T&gt; but T. We don't create any rv&lt;T&gt; object so downcasting T to a non-existent rv&lt;T&gt; object is at least doubtful. </p> </blockquote> <p> Ah, I didn't realize that. So there are no objects whose dynamic type is rv&lt;T&gt;. That would mean the static downcast is hitting the "undefined behavior" case at the end of 5.2.9/8. And if the compiler can figure that out (that the T* really can't be an rv&lt;T&gt;*) then it can generate pretty much any old garbage code. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Ion Gaztañaga</dc:creator> <pubDate>Thu, 26 Aug 2010 10:18:38 GMT</pubDate> <title>status, milestone changed; resolution set https://svn.boost.org/trac10/ticket/3950#comment:11 https://svn.boost.org/trac10/ticket/3950#comment:11 <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> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.43.0</span> → <span class="trac-field-new">Boost-1.45.0</span> </li> </ul> <p> Fixed for Boost 1.45 in release branch </p> Ticket