ошибка сегментации в итераторе

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

Я пытаюсь перебрать значения каждой ключевой точки и создать сегмент дороги в каждой точке дороги (кроме последней), настроить значения так, чтобы они находились в точках дороги, а затем сохранить их в std::vector.

Конструктор RoadSegment создает 6 точек vec3 и помещает их в std::vector.

У меня ошибка сегментации в строке, выделенной жирным шрифтом [for(mapIt = it.first; mapIt != it.second; ++mapIt)]

Когда я убираю строки, создающие новые объекты, и помещаю их в std::vector, все работает нормально.

Может кто подскажет в чем проблема/решение проблемы???

Спасибо заранее

std::vector<glm::vec3>::iterator SegIt;

for(int i = 0; i < m_genRoads->getKeyValueData().size(); i++)
{
    int numberDesired = m_genRoads->getMultimapData().count(i) - 1;

    std::multimap<int, glm::vec3>::iterator mapIt;
    std::pair<std::multimap<int, glm::vec3>::iterator, std::multimap<int, glm::vec3>::iterator> it;

    it = m_genRoads->getMultimapData().equal_range(i);


    for(mapIt = it.first; mapIt != it.second; ++mapIt)
    {

        int distance = std::distance(it.first, mapIt);

        if(distance != numberDesired)
        {
            RoadSegement* roadSegmentPointer = new RoadSegement();

            // FUNCTIONS TO ADJUST COORD VALUES TO MATCH THE ROAD POINTS


            m_segmentArray.push_back(roadSegmentPointer);

        }

        else
        {
            continue;
        }

         ///SOME BUFFER BINDING STUFF 

person willgosling    schedule 05.01.2015    source источник
comment
вероятно, с помощью ++mapIt вы выходите за пределы своей карты. попробуй изменить в mapIt++   -  person Frank Cunningham    schedule 05.01.2015
comment
Я только что попробовал это, но это не сработало .... все еще дает ошибку сегментации   -  person willgosling    schedule 05.01.2015
comment
@FrankCunningham: ++mapIt и mapIt++ делают одно и то же; единственная разница заключается в значении выражения (до или после приращения), которое этот код игнорирует.   -  person Scott Hunter    schedule 05.01.2015
comment
Можете ли вы уточнить, когда и где возникает ошибка? Какая итерация, например?   -  person Scott Hunter    schedule 05.01.2015
comment
@willgosling Пожалуйста, опубликуйте getMultimapData(). Я чувствую, что вы возвращаете временный.   -  person PaulMcKenzie    schedule 05.01.2015
comment
Я вставил std::cout непосредственно перед новым RoadSegment(). Он печатает один раз, а затем останавливается   -  person willgosling    schedule 05.01.2015
comment
std::multimap‹int, glm::vec3> GenerateRoads::getMultimapData() { return m_roadsMultimap; }   -  person willgosling    schedule 05.01.2015
comment
m_roadsMultimap — это std::multimap‹int, glm::vec3›   -  person willgosling    schedule 05.01.2015
comment
@willgosling Бинго, вот в чем проблема. Вы возвращаете временную карту. Этот парень ушел, и любое использование его итератора недействительно.   -  person PaulMcKenzie    schedule 05.01.2015
comment
но если я удалю строки RoadSegment *roadSegmentPointer = new RoadSegment(); m_segmentArray.push_back (roadSegentPointer); и замените его на std::cout‹‹MAKE ROAD SEGMENT‹‹std::endl; работает нормально и печатает несколько раз   -  person willgosling    schedule 05.01.2015
comment
@willgosling - Внесите изменения, предложенные в ответе. Ваш код вызывает неопределенное поведение с помощью недопустимых итераторов, поэтому удаление/добавление строк кода на самом деле не делает ничего полезного (кроме демонстрации того, как плохой код может делать странные вещи).   -  person PaulMcKenzie    schedule 05.01.2015
comment
Реализации основных стандартных библиотек поддерживают проверенные итераторы для отладки, которые мгновенно обнаружили бы эту проблему. например для GCC попробуйте скомпилировать свой код с помощью -D_GLIBCXX_DEBUG, чтобы использовать контейнеры режима отладки, который прервется, как только вы попытаетесь использовать недопустимый итератор.   -  person Jonathan Wakely    schedule 05.01.2015


Ответы (1)


Похоже, проблема в том, что вы используете несуществующие итераторы, и все из-за возврата временного объекта.

it = m_genRoads->getMultimapData().equal_range(i);

Поскольку getMultiMapData() возвращает копию мультикарты, эта мультикарта исчезает после выполнения строки, что делает любые итераторы недействительными.

Одним из решений является возврат ссылки на мультикарту, а не новую копию мультикарты.

std::multimap<int, glm::vec3>& GenerateRoads::getMultimapData() { return m_roadsMultimap; }

person PaulMcKenzie    schedule 05.01.2015
comment
Это здорово, это работает, спасибо. Означает ли это, что любая функция, которая вызывает возврат, который используется в цикле, должна возвращать ссылку или это зависит от конкретного случая? - person willgosling; 05.01.2015
comment
К петлям отношения не имеет. Вы просто не можете использовать итератор для несуществующего контейнера. Возврат из функции по значению создает новый временный объект, который затем снова исчезает, поэтому любые итераторы в этот временный объект немедленно становятся недействительными. - person Jonathan Wakely; 05.01.2015
comment
Проблема заключается в сроке службы объекта. В вашем исходном коде возвращаемое мультиотображение будет длиться до следующего оператора. Возвращая ссылку, вы возвращаете ту же мультикарту, которую использовал ваш класс, а не копию. В возврате копии нет ничего плохого по своей сути, но вы должны убедиться, что копия существует столько, сколько вы хотите, а в вашем случае это не так. - person PaulMcKenzie; 05.01.2015
comment
Ааа ок я вижу. Большое спасибо за помощь :) - person willgosling; 05.01.2015