Я знаю, что повышение или компилятор должны быть в последний раз виноваты, но я не вижу другое объяснение здесь. Я использую msvc 2008 SP1 и повышение 1.43.
В следующем выполнении фрагмента кода никогда не оставляет третий цикл BOOST_FOREACH
typedef Graph::VertexIterator Iter;
Graph g;
g.createVertex(0x66);
// works fine
Iter it = g.getVertices().first, end = g.getVertices().second;
for(; it != end; ++it)
;
// fine
std::pair 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
{
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 *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::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 одним получением из станд.:: итератор и сохраненная проблема, таким образом, это не отказ iterator_facade. Эта проблема существует только на msvc 2008 SP1 x86 и amd64 сборках конечных версий. Отладка основывается на msvc 2008, и отладка/сборки конечных версий на msvc 2010 и (Linux) gcc 4.4 хорошо работает. Кроме того, блок BOOST_FOREACH должен быть повторен exacly 10 раз. Если это повторилось 9 раз, это - весь OK.
Я предполагаю, что из-за использования BOOST_FOREACH шаблонного обмана (константа auto_any), компилятор предполагает, что дескриптор итератора является постоянным и никогда не читает свое действительное значение снова.
Я был бы очень рад услышать, что мой код является неверным, исправьте его и движение с BOOST_FOREACH, из которого я очень найден (в противоположность BOOST_FOREVER :).
Может быть связан с: Почему BOOST_FOREACH иногда не работает со строками C++?
Править:
Я подготовил упрощенный проект, воспроизводящий проблему. Никакие шаблоны, никакие параметрические усилители по умолчанию, нет ничто. Получите его здесь: http://yabcok.nazwa.pl/ugly3.zip
Мне кажется, эта ошибка в VC ++ относительно значений по умолчанию в шаблонных функциях.
Есть очень похожая ошибка здесь в августе 2009 года (закрыта как «исправленная» M $ в их следующем выпуске) ... она согласована во многих отношениях: она специфична для VC ++ и работает в GCC, приводит к периодическому сбою с аргументами шаблона по умолчанию (но никогда к проблемам во время компиляции), и проблема возникает только во втором экземпляре.
Тем не менее, я не могу объяснить вывод компилятора или волшебные 10 циклов ...: -)
VC ++ даже имеет старую статью о обходных путях с шаблонами . с очень похожими ошибками совсем недавно и насколько последовательными кажутся ваша ошибка и ошибка Color_of_Green, вероятно, это VC ++, а не Boost.
Какое предположение? Он задыхается от этих сигнатур: const T & data = T ()
в graph_elements_collection.h. MSFT рекомендует изменить это на const T data = T ()
. Чтобы убедиться, что это связано с этой ошибкой компилятора, попробуйте ее или обходные пути, опубликованные MSFT ... здесь ...