Я работаю над пользовательским интерфейсом. Базовый класс для компонента пользовательского интерфейса UILayout
, а весь пользовательский интерфейс представляет собой дерево объектов UILayout, а корень UILayout представляет весь экран. Чтобы содержать эту иерархию, любой заданный UILayout имеет вектор mChildren из boost::shared_ptr<UILayout>
.
Объект UIManager заботится об обновлении всей иерархии UILayouts. Каждый вызов Update повторяет вектор mChildren, рекурсивно вызывая Update для каждого дочернего элемента.
Поскольку изменение формы вектора лишит законной силы эти итераторы, добавление и удаление записей из mChildren ограничивается методом ResizeChildren. Когда необходимо добавить или удалить компоненты, они добавляются в один из двух векторов, mChildrenPendingAddition и mChildrenPendingRemoval. Непосредственно перед циклом обновления вызывается ResizeChildren, и mChildren обновляется соответствующим образом. (Пожалуйста, остановите меня, если это единственный способ решения этой конкретной проблемы.)
Я получаю исключение, когда пытаюсь удалить из mChildren все записи, которые также содержатся в mChildrenPendingRemoval. Из UILayout :: ResizeChildren ():
mChildren.erase(remove_if(mChildren.begin(), mChildren.end(),
IntersectsWithChildrenPendingRemoval(this)), mChildren.end());
Функция сравнения IntersectsWithChildrenPendingRemoval вызывает this-> ChildrenPendingRemovalContains (HUILayout ly), который выполняет следующие действия:
return (find(mChildrenPendingRemoval.begin(), mChildrenPendingRemoval.end(),
ly) != mChildrenPendingRemoval.end());
Эта строка иногда не проходит утверждение отладки несовместимые векторные итераторы . Существует множество существующих вопросов по этой ошибке, но, похоже, она обычно указывает на то, что сравниваются два итератора из разных контейнеров. Но здесь это явно не так, верно? Что еще может вызвать эту проблему?
Соответствующий исходный код:
Это плагин, который я разрабатываю для многопоточного приложения. Тот факт, что проблема возникает с очень редкими и случайными интервалами, заставляет меня поверить, что это как-то связано с тем, что плагин работает в отдельных потоках, но все эти методы вызываются из одной функции, прямо в одной нить, а mChildren не доступен и не изменен ни в каком другом потоке.