问题描述
我知道,升压或编译器应该是最后的指责,但我不能在这里看到另一种解释。
我使用的是MSVC 2008 SP1和提升1.43。
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.
在以下code段执行从未离开第三 BOOST_FOREACH循环
In the following code snippet execution never leaves third BOOST_FOREACH loop
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
迭代code:
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乐趣:
Some ASM fun:
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,它从来没有得到,尽管调用迭代器符++()函数递增。结果
我把它换成Itarator implmentation从的std ::迭代器1推导和问题依然存在,所以这不是iterator_facade故障。
这个问题只存在于MSVC 2008 SP1 x86和AMD64发布版本。调试建立在2008年MSVC和调试/发布版本的MSVC 2010和gcc 4.4(Linux)的正常工作。
此外,BOOST_FOREACH块必须repeaded exacly 10倍。如果它repeaded 9倍,这是一切OK。
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.
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.
我猜,由于BOOST_FOREACH使用模板挂羊头卖狗肉(常量auto_any)中,编译器假定迭代器手柄是恒定的,不会再读取其真正的价值。
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.
我会很高兴地听到,我的code是错误的,正确的,并与BOOST_FOREACH,我感到非常的发现(而不是BOOST_FOREVER:)前进。
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 :).
可能与:http://stackoverflow.com/questions/1275852/why-does-boost-foreach-not-work-sometimes-with-c-strings
编辑:
我已经prepared简化项目重现的问题。没有模板,没有默认参数,可以什么都没有。在这里获得:
I've prepared simplified project reproducing the problem. No templates, no default params, no nothing. Get it here: http://yabcok.nazwa.pl/ugly3.zip
推荐答案
尝试添加/ Oy-编译器标志(配置属性 - > C / C ++ - >优化 - >禁用省略帧指针)
Try to add the /Oy- compiler flag (Configuration Properties -> C/C++ -> Optimization -> Disable "Omit Frame Pointer")
我是有使用2010 MSVC同样的问题,这解决了!
I was having the same problem using MSVC 2010, and this solved it!
这篇关于需要与BOOST_FOREACH /编译器错误帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!