需要帮助BOOST_FOREACH /编译器错误

时间:2010-05-21 11:09:09

标签: c++ visual-c++ boost boost-foreach

我知道升压或编译应该是最后的责任,但我在这里看不到另一种解释。 我正在使用msvc 2008 SP1并提升1.43。

在以下代码段执行中永远不会离开第三个 BOOST_FOREACH循环

typedef Graph<unsigned, unsigned>::VertexIterator Iter;

Graph<unsigned, unsigned> g;
g.createVertex(0x66);

// works fine
Iter it = g.getVertices().first, end = g.getVertices().second;
for(; it != end; ++it)
    ;

// fine
std::pair<Iter, Iter> 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

迭代器代码:

class Iterator 
    : public boost::iterator_facade<Iterator, unsigned const, 
                boost::bidirectional_traversal_tag>
{
public:
    Iterator()
        : list(NULL), handle(INVALID_ELEMENT_HANDLE)
    {}

    explicit Iterator(const VectorElementsList &list, unsigned handle = INVALID_ELEMENT_HANDLE)
        : list(&list), handle(handle)
    {}

    friend std::ostream& 
    operator<<(std::ostream &s, const Iterator &it)
    {
        s << "[list: " << it.list <<", handle: " << it.handle << "]";
        return s;
    }

private:
    friend class boost::iterator_core_access;

    void increment()
    {
        handle = list->getNext(handle);
    }

    void decrement() 
    {
        handle = list->getPrev(handle);
    }

    unsigned const& dereference() const
    {
        return handle; 
    }

    bool equal(Iterator const& other) const
    {
        return handle == other.handle && list == other.list;
    }

    const VectorElementsList<T> *list;
    unsigned handle;
};

一些ASM乐趣:

    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<detail::VectorElementsList<Graph<unsigned int,unsigned int>::VertexWrapper>::Iterator,unsigned int const ,boost::bidirectional_traversal_tag,unsigned int const &,int>::operator++ (13E18E0h) 
013E1392  jmp         main+230h (13E1380h) 
        vertex_count++;
// forever loop end

很容易看到迭代器句柄缓存在EBP中,尽管调用了迭代器operator ++()函数,但它永远不会增加。
我用一个派生自std :: iterator的替换了Itarator implmentation并且问题仍然存在,所以这不是iterator_facade错误。 此问题仅存在于msvc 2008 SP1 x86和amd64发布版本上。调试构建在msvc 2008和msvc 2010上的调试/发布版本上,gcc 4.4(linux)工作正常。 此外,BOOST_FOREACH块必须重复执行10次。如果它被重复9次,那就没关系了。

我想由于BOOST_FOREACH使用模板技巧(const auto_any),编译器假定迭代器句柄是常量并且永远不再读取它的实际值。

我会很高兴听到我的代码错误,纠正它并继续使用BOOST_FOREACH,我很发现它(与BOOST_FOREVER相反:)。

可能与:Why does BOOST_FOREACH not work sometimes with C++ strings?

有关

修改

我准备了简化的项目来重现这个问题。没有模板,没有默认参数,没有任何东西。在此处获取:http://yabcok.nazwa.pl/ugly3.zip

2 个答案:

答案 0 :(得分:2)

尝试添加/ Oy-编译器标志(配置属性 - &gt; C / C ++ - &gt;优化 - &gt;禁用“省略帧指针”)

我在使用MSVC 2010时遇到了同样的问题,这解决了它!

答案 1 :(得分:1)

对我这样看bug in VC++关于模板函数中的默认值。

2009年8月出现了一个非常类似的错误here(在下一个版本中由M $关闭为“固定”)......它以多种方式保持一致:它是VC ++特定的并且在GCC中工作,导致使用默认模板参数的间歇性失败(但绝不会发生编译时问题),并且问题只会在第二次实例化时出现。

那说,我无法解释编译器输出,或魔术10循环......: - )

VC ++甚至在workarounds with templates上有一篇旧文章。最近有非常相似的错误,以及你的bug和Color_of_Green的bug看起来如何一致,它可能是VC ++,而不是Boost。

我的猜测?这些签名令人窒息:graph_elements_collection.h中的const T & data = T()。 MSFT建议将其更改为const T data = T()。要验证它与此编译器错误有关,请尝试使用,或MSFT发布的变通办法...... here ...