Note that there are some explanatory texts on larger screens.

plurals
  1. PONeed help with BOOST_FOREACH/compiler bug
    text
    copied!<p>I know that boost or compiler should be last to blame, but I can't see another explanation here. I'm using msvc 2008 SP1 and boost 1.43. </p> <p>In the following code snippet execution never leaves <strong>third</strong> BOOST_FOREACH loop</p> <pre><code>typedef Graph&lt;unsigned, unsigned&gt;::VertexIterator Iter; Graph&lt;unsigned, unsigned&gt; g; g.createVertex(0x66); // works fine Iter it = g.getVertices().first, end = g.getVertices().second; for(; it != end; ++it) ; // fine std::pair&lt;Iter, Iter&gt; p = g.getVertices(); BOOST_FOREACH(unsigned handle, p) ; // fine unsigned vertex_count = 0; BOOST_FOREACH(unsigned handle, g.getVertices()) vertex_count++; // oops, infinite loop vertex_count = 0; BOOST_FOREACH(unsigned handle, g.getVertices()) vertex_count++; vertex_count = 0; BOOST_FOREACH(unsigned handle, g.getVertices()) vertex_count++; // ... last block repeated 6 times </code></pre> <p>Iterator code:</p> <pre><code>class Iterator : public boost::iterator_facade&lt;Iterator, unsigned const, boost::bidirectional_traversal_tag&gt; { public: Iterator() : list(NULL), handle(INVALID_ELEMENT_HANDLE) {} explicit Iterator(const VectorElementsList &amp;list, unsigned handle = INVALID_ELEMENT_HANDLE) : list(&amp;list), handle(handle) {} friend std::ostream&amp; operator&lt;&lt;(std::ostream &amp;s, const Iterator &amp;it) { s &lt;&lt; "[list: " &lt;&lt; it.list &lt;&lt;", handle: " &lt;&lt; it.handle &lt;&lt; "]"; return s; } private: friend class boost::iterator_core_access; void increment() { handle = list-&gt;getNext(handle); } void decrement() { handle = list-&gt;getPrev(handle); } unsigned const&amp; dereference() const { return handle; } bool equal(Iterator const&amp; other) const { return handle == other.handle &amp;&amp; list == other.list; } const VectorElementsList&lt;T&gt; *list; unsigned handle; }; </code></pre> <p>Some ASM fun:</p> <pre><code> vertex_count = 0; BOOST_FOREACH(unsigned handle, g.getVertices()) // initialization 013E1369 mov edi,dword ptr [___defaultmatherr+8 (13E5034h)] // end iterator handle: 0xFFFFFFFF 013E136F mov ebp,dword ptr [esp+0ACh] // begin iterator handle: 0x0 013E1376 lea esi,[esp+0A8h] // begin iterator list pointer 013E137D mov ebx,esi 013E137F nop // forever loop begin 013E1380 cmp ebp,edi 013E1382 jne main+238h (13E1388h) 013E1384 cmp ebx,esi 013E1386 je main+244h (13E1394h) 013E1388 lea eax,[esp+18h] 013E138C push eax // here iterator is incremented in ram 013E138D call boost::iterator_facade&lt;detail::VectorElementsList&lt;Graph&lt;unsigned int,unsigned int&gt;::VertexWrapper&gt;::Iterator,unsigned int const ,boost::bidirectional_traversal_tag,unsigned int const &amp;,int&gt;::operator++ (13E18E0h) 013E1392 jmp main+230h (13E1380h) vertex_count++; // forever loop end </code></pre> <p>It's easy to see that iterator handle is cached in EBP and it never gets incremented despite of a call to iterator operator++() function.<br> I've replaced Itarator implmentation with one deriving from std::iterator and the issue persisted, so this is not iterator_facade fault. This problem exists only on msvc 2008 SP1 x86 and amd64 release builds. Debug builds on msvc 2008 and debug/release builds on msvc 2010 and gcc 4.4 (linux) works fine. Furthermore the BOOST_FOREACH block must be repeaded exacly 10 times. If it's repeaded 9 times, it's all OK. </p> <p>I guess that due to BOOST_FOREACH use of template trickery (const auto_any), compiler assumes that iterator handle is constant and never reads its real value again.</p> <p>I would be very happy to hear that my code is wrong, correct it and move on with BOOST_FOREACH, which I'm very found of (as opposed to BOOST_FOREVER :).</p> <p>May be related to: <a href="https://stackoverflow.com/questions/1275852/why-does-boost-foreach-not-work-sometimes-with-c-strings">Why does BOOST_FOREACH not work sometimes with C++ strings?</a></p> <p><strong>EDIT:</strong></p> <p>I've prepared simplified project reproducing the problem. No templates, no default params, no nothing. Get it here: <a href="http://yabcok.nazwa.pl/ugly3.zip" rel="nofollow noreferrer">http://yabcok.nazwa.pl/ugly3.zip</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload