gpt4 book ai didi

c++ - 需要有关 BOOST_FOREACH/编译器错误的帮助

转载 作者:IT老高 更新时间:2023-10-28 22:41:51 25 4
gpt4 key购买 nike

我知道应该最后归咎于 boost 或编译器,但我在这里看不到其他解释。我正在使用 msvc 2008 SP1 和 boost 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++() 函数,但它永远不会递增。
我已将 Itarator 实现替换为源自 std::iterator 的实现,并且问题仍然存在,因此这不是 iterator_facade 错误。此问题仅存在于 msvc 2008 SP1 x86 和 amd64 发行版本上。在 msvc 2008 上构建调试,在 msvc 2010 和 gcc 4.4 (linux) 上构建调试/发布工作正常。此外,BOOST_FOREACH block 必须精确重复 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

最佳答案

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

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

关于c++ - 需要有关 BOOST_FOREACH/编译器错误的帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2881491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com