std::vector Assertion failed (векторные итераторы несовместимы)

У меня есть эта структура:

struct MxMInstanceData
{
    D3DXVECTOR2 mTransform;
    float mSpacing;
};

Затем я создаю вектор MxMInstanceData:

std::vector<MxMInstanceData> instInFrustumData;

Если я позвоню instInFrustumData.clear(), я получаю эту ошибку:

Утверждение не выполнено (векторные итераторы несовместимы)

Код создания вектора:

instInFrustumData.reserve(mNumInstances);

Код обновления вектора:

void Terrain::updateInstances()
{
    mNumInstancesInFrustum = 0;

    if(instInFrustumData.size() != 0)
        instInFrustumData.clear();

    mpMxMInstInFrustumB->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**) &instInFrustumData);

    for(int x = 0; x < mNumInstances; x++)
    {
        if(mpCamera->point2DInFrustum(instData[x].mTransform + 
            D3DXVECTOR2(instData[x].mSpacing/2 + mpCamera->getPosition().x, instData[x].mSpacing/2 + mpCamera->getPosition().z), instData[x].mSpacing/2)
            != OUTSIDE)
        {
            instInFrustumData.push_back(instData[x]);
            mNumInstancesInFrustum++;
        }
    }

    mpMxMInstInFrustumB->Unmap();
}

Что может заставить это произойти?

И в деструкторе моего класса я также вызываю clear()


person Tiago Costa    schedule 28.04.2011    source источник
comment
Ваш размещенный код не может - так что публикуйте больше.   -  person Erik    schedule 28.04.2011
comment
Я нашел еще одну вещь: после создания вектора я изменяю его размер так, что размер = емкость. Я вызываю очистку() и все в порядке, поэтому размер = 0 емкость = 100, затем я заполняю ее только 8 значениями, и когда я снова вызываю очистку (во второй раз), выдается ошибка   -  person Tiago Costa    schedule 28.04.2011
comment
Что-то, что может сделать это взаимозаменяемым, использует константные и неконстантные итераторы. Однако вам нужно опубликовать свой фактический код, потому что то, что у вас есть, не вызывает этой ошибки.   -  person AJG85    schedule 28.04.2011
comment
Да, это также потенциально не связано, поэтому вы все равно должны просто опубликовать свой фактический код, используя вектор в полной форме. Обратите внимание, однако, что вы должны использовать reserve для резервирования емкости в векторе без создания элементов. resize удалит элементы или расширит вектор и потенциально создаст новые пустые элементы в зависимости от текущего размера и элементов, присутствующих при его вызове.   -  person AJG85    schedule 28.04.2011
comment
Сначала я использовал резерв, затем изменил размер, но ошибка осталась...   -  person Tiago Costa    schedule 28.04.2011


Ответы (2)


Вы можете проверить справку по использованию std::vector, например http://www.cplusplus.com/reference/stl/vector/ или купите хорошую книгу STL. Вы используете некоторые методы, которые я бы назвал неортодоксальными.

  • Используйте empty(), чтобы проверить, есть ли в векторе элементы (если он не пустой, просто читается лучше)
  • Используйте локальные переменные, когда это возможно (вещи, которые не должны оставаться в области видимости, не должны)
  • Используйте итераторы STL или размеры контейнеров в циклах (необходимо ли иметь два возрастающих целых числа в одном цикле?)
  • Используйте "лучший" контейнер STL для своей реализации (вам нужны векторы или карты?)
  • Избегайте приведения типов в стиле C и неправильного использования объектов ((void**) &instInFrustumData — очень плохая идея)

У вас так много переменных-членов, определение которых неизвестно, а также неизвестные методы Map() и UnMap() и до сих пор не показано никакого кода с использованием итераторов, связанного с вашей исходной ошибкой. Я предполагаю, что ваше использование instData[x] опасно и проблематично, как и способ построения этого цикла в целом. Вы также действительно не хотите рассматривать контейнеры STL как нечто иное, как контейнеры STL. Следует избегать таких вещей, как (void**) &instInFrustumData, так как они могут вызвать только проблемы.

Я настоятельно рекомендую вам сначала изучить C++, прежде чем браться за DirectX или графические и игровые движки, написанные на обоих.

person AJG85    schedule 28.04.2011
comment
Методы Map() и Unmap() являются методами DirectX ID3D10Buffer (поэтому я не опубликовал полный код, когда впервые написал этот вопрос, потому что знал, что это вызовет некоторую путаницу), поэтому необходимо выполнить приведение (void**) &instInFrustumData . - person Tiago Costa; 28.04.2011
comment
Это нормально. Похоже, что требуется выходной параметр памяти для записи, возможно, для рисования позже. Не лучшая идея раскрывать внутренности вектора STL для прямой записи чем-то, не разработанным с учетом STL. Если вы ДОЛЖНЫ, то я бы, вероятно, использовал &instInFrustumData.data(), но, честно говоря, я бы предпочел использовать в этом случае массив байтов, а затем заполнять свой вектор в коде, которым я управляю. - person AJG85; 28.04.2011
comment
Я только что посмотрел метод ... Map() и Unmap(), похоже, являются блокирующими механизмами для буфера. Возможно, было бы предпочтительнее использовать что-то большее в строках boost::mutex и boost::mutex::scoped_lock или какую-либо другую блокировку на основе мьютекса для управления доступом на запись к вашему вектору. Если нет, попробуйте вместо этого использовать &instInFrustumData.data(), так как это фактически указатель на внутренний буфер, в котором выделена память вектора. - person AJG85; 28.04.2011
comment
instInFrustumData.data() исправил это, большое спасибо :D. Не могли бы вы сказать мне название хорошей книги по STL, потому что я знаю только основы STL... Я даже не знал о существовании метода data()... Также я не знаком с пространством имен boost. Я также куплю книгу о более продвинутом C++, потому что та, что у меня есть, действительно базовая, поэтому я даже не знаю, что такое шаблоны и т. Д.: S - person Tiago Costa; 28.04.2011
comment
boost.org – это отличная сторонняя библиотека C++, которая настолько хороша, что большая часть ее используется в новый стандарт C++ и частично доступен в новой форме в пространстве имен std::tr1. Что касается книг, я бы порекомендовал что-нибудь Скотта Мейерса или Херба Саттера для действительно хороших советов и приемов, но для справки ознакомьтесь с этой статьей: stackoverflow.com/questions/388242/ - person AJG85; 30.04.2011

Здесь можно угадать, но, возможно, ваша проблема в этой строке:

mpMxMInstInFrustumB->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**) &instInFrustumData);

Вы передаете указатель на сам вектор этой функции Map, которая, как я предполагаю, может перезаписывать некоторые из его внутренних компонентов? У меня нет его документации, но это не похоже на функцию, ожидающую указатель на вектор :)

person Luke Halliwell    schedule 28.04.2011