Boost C++ Libraries: Ticket #8395: Valgrind error in lockfree::queue https://svn.boost.org/trac10/ticket/8395 <p> The following code </p> <pre class="wiki">#include &lt;boost/lockfree/queue.hpp&gt; int main() { int i = 0; boost::lockfree::queue&lt;int*&gt; q(128); q.push(&amp;i); q.push(&amp;i); return 0; } </pre><p> compiled with </p> <pre class="wiki">g++ -o test test.cpp -I/opt/boost/include </pre><p> produces the following valgrind output </p> <pre class="wiki">==32040== Memcheck, a memory error detector ==32040== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==32040== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==32040== Command: ./test ==32040== ==32040== Conditional jump or move depends on uninitialised value(s) ==32040== at 0x401E77: boost::atomics::detail::base_atomic&lt;boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;, void, 8u, false&gt;::compare_exchange_strong(boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;&amp;, boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt; const&amp;, boost::memory_order, boost::memory_order) volatile (in /tmp/test) ==32040== by 0x401DD9: boost::atomics::detail::base_atomic&lt;boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;, void, 8u, false&gt;::compare_exchange_weak(boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;&amp;, boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt; const&amp;, boost::memory_order, boost::memory_order) volatile (in /tmp/test) ==32040== by 0x4019E0: boost::atomics::detail::base_atomic&lt;boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;, void, 8u, false&gt;::compare_exchange_weak(boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;&amp;, boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt;, boost::memory_order) volatile (in /tmp/test) ==32040== by 0x40121C: bool boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::do_push&lt;false&gt;(int* const&amp;) (in /tmp/test) ==32040== by 0x400CF6: boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::push(int* const&amp;) (in /tmp/test) ==32040== by 0x40097E: main (in /tmp/test) ==32040== ==32040== Conditional jump or move depends on uninitialised value(s) ==32040== at 0x40121F: bool boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::do_push&lt;false&gt;(int* const&amp;) (in /tmp/test) ==32040== by 0x400CF6: boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::push(int* const&amp;) (in /tmp/test) ==32040== by 0x40097E: main (in /tmp/test) ==32040== ==32040== ==32040== HEAP SUMMARY: ==32040== in use at exit: 0 bytes in 0 blocks ==32040== total heap usage: 129 allocs, 129 frees, 8,256 bytes allocated ==32040== ==32040== All heap blocks were freed -- no leaks are possible ==32040== ==32040== For counts of detected and suppressed errors, rerun with: -v ==32040== Use --track-origins=yes to see where uninitialised values come from ==32040== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2) </pre><p> This might be an issue with the atomic library, but I have not been able to track it further. </p> <p> OS is Fedora F18 (3.8.3-203.fc18.x86_64) </p> <p> G++ is g++ (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8) </p> <p> Valgrind is valgrind-3.8.1 </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/8395 Trac 1.4.3 adam@… Fri, 05 Apr 2013 13:04:58 GMT attachment set https://svn.boost.org/trac10/ticket/8395 https://svn.boost.org/trac10/ticket/8395 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">lockfree.patch</span> </li> </ul> <p> Patch to correct valgrind issue (as applied to version 1.53) </p> Ticket adam@… Fri, 05 Apr 2013 13:10:43 GMT <link>https://svn.boost.org/trac10/ticket/8395#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:1</guid> <description> <p> I've attached a patch (<a class="attachment" href="https://svn.boost.org/trac10/attachment/ticket/8395/lockfree.patch" title="Attachment 'lockfree.patch' in Ticket #8395">attachment:lockfree.patch</a><a class="trac-rawlink" href="https://svn.boost.org/trac10/raw-attachment/ticket/8395/lockfree.patch" title="Download">​</a>) that resolves the issue for me. </p> <p> Note that this basically involves uncommenting the initialisation of the next pointer in the queue::node structure. However, it looks very much like the code relies on this being uninitialised - so this patch probably breaks something else. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>timblechmann</dc:creator> <pubDate>Fri, 05 Apr 2013 13:25:00 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8395#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:2</guid> <description> <p> i will have to review this specific part carefully. the uninitialized part is related to the ABA prevention counter, simply initializing it may silent the valgrind warning, but introduce an ABA problem, so this patch might break the data structure in a very subtle way. </p> <p> this issue could possibly be considered as `false positive' and the better way to silence the warning, might be to initialize the memory region, not in the constructor, but when allocating memory from the OS. </p> <p> might take me some time to review all the code ... </p> </description> <category>Ticket</category> </item> <item> <author>adam@…</author> <pubDate>Fri, 05 Apr 2013 13:55:54 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/8395 https://svn.boost.org/trac10/ticket/8395 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">lockfree2.patch</span> </li> </ul> <p> Revised patch that uses a custom allocator to zero initialise nodes. </p> Ticket adam@… Fri, 05 Apr 2013 13:57:37 GMT <link>https://svn.boost.org/trac10/ticket/8395#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:3</guid> <description> <p> Having delved a little further I concur, the patch was more of a confirmation for me of where the warning was coming from. </p> <p> On further analysis: </p> <p> The warning does not occur if the container is not given a size at construction: </p> <pre class="wiki">boost::lockfree::queue&lt;int*&gt; q; </pre><p> and appears to be caused by the allocation, but not construction, of all the nodes in the freelist class. </p> <p> If I understand correctly, it doesn't matter that the next tag is uninitialised, the only important thing is that the new tag is different to the old tag for tags that reside at the same address - so in that sense, this is a false positive (and the patch is bad!). </p> <p> One option would be to add a constructor or policy to the freelist class that caused it to zero initialise memory on allocation, or to use a custom allocator with the same behaviour, which I think would suppress the warning. I don't think this would cause any issues because the freelist doesn't do any "real" deallocation until destruction. </p> <p> I've attached another patch (<a class="attachment" href="https://svn.boost.org/trac10/attachment/ticket/8395/lockfree2.patch" title="Attachment 'lockfree2.patch' in Ticket #8395">attachment:lockfree2.patch</a><a class="trac-rawlink" href="https://svn.boost.org/trac10/raw-attachment/ticket/8395/lockfree2.patch" title="Download">​</a>) that implements the custom allocator strategy. Again, this appears to successfully suppress the valgrind warning, I can't say whether or not there are other unintended side effects though. </p> </description> <category>Ticket</category> </item> <item> <author>breese@…</author> <pubDate>Sat, 13 Sep 2014 13:47:35 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8395#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:4</guid> <description> <p> I get the same valgrind report. Furthermore, I get a similar report if I change the queue to use boost::lockfree::capacity&lt;128&gt;. </p> <p> I am not so sure that valgrind is reporting a false positive. An uninitialized value means that it could be any value, including the one that causes the ABA problem. </p> <p> Unfortunately, applying the second patch to the develop branch does not make the reports disappear. </p> </description> <category>Ticket</category> </item> <item> <author>w.goesgens@…</author> <pubDate>Tue, 19 Jan 2016 16:11:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8395#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:5</guid> <description> <p> Is there any news on this? The patches wouldn't fix it for me, and the noise in valgrind is really anoying... </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Mon, 12 Dec 2016 14:24:20 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8395#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:6</guid> <description> <p> Same here.Valgrind outputs a 'Conditional jump or move depends on uninitialised value(s)' about it. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sun, 16 Apr 2017 05:31:19 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8395#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8395#comment:7</guid> <description> <p> Same here with boost 1.58. Compiled in debug with --track-origins=yes, I have: </p> <pre class="wiki">==10410== Conditional jump or move depends on uninitialised value(s) ==10410== at 0x401939: compare_exchange_weak (ops_gcc_atomic.hpp:132) ==10410== by 0x401939: compare_exchange_weak (atomic_template.hpp:386) ==10410== by 0x401939: compare_exchange_weak (atomic_template.hpp:393) ==10410== by 0x401939: bool boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::do_push&lt;false&gt;(int* const&amp;) (queue.hpp:307) ==10410== by 0x400C48: boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::push(int* const&amp;) (queue.hpp:267) ==10410== by 0x4008DC: main (plap.cpp:9) ==10410== Uninitialised value was created by a stack allocation ==10410== at 0x40361E: boost::atomics::atomic&lt;boost::lockfree::detail::tagged_ptr&lt;boost::lockfree::queue&lt;int*, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_&gt;::node&gt; &gt;::atomic() (atomic_template.hpp:680) </pre> </description> <category>Ticket</category> </item> </channel> </rss>