Итератор для бесконечного цикла по списку - PullRequest
2 голосов
/ 24 октября 2019

Я использую итератор в цикле for, и по какой-то причине он зацикливается бесконечно. Похоже, что он делает то, что должен делать, просто бесконечно.

Просмотр других подобных вопросов не помог мне решить мою проблему, поскольку я нигде не использую сплайсинг и пробовал много разных способов реализации этого цикла (поскольку, используя int для условного цикла, используясам итератор, продвижение итератора и т. д.). Наибольший прогресс, который я получил, - вместо этого получить недопустимое чтение (см. Ниже).

Я дважды проверил код, чтобы убедиться, что я не манипулировал указателями итератора напрямую (возможно, создавая ситуацию, когда list.end () = list.begin ()) но не смог найти ничего подобного. Все, что я использовал для этого конкретного списка, было находить, вставлять и очищать.

Я перебираю список пар, состоящий из указателя структуры REG и целого числа. Это скомпилировано в C ++ 11 с -Wall и -Wextra.

Модифицируя его чем-либо, чтобы контролировать его, чтобы он остановился на последнем элементе (используя .size (), или проверяя, находится ли та же позицияvector colors [] уже равен 1), что приводит к недопустимой ошибке чтения.

int getAvailableColor(int K, std::list<std::pair<REG*, int>> adjacency)
{
   std::list<std::pair<REG*, int>>::iterator it;   
   int Ko = K;                                     
   int colors[K];                                  

   for(int i = 0; i < Ko; i++)
   {
       colors[i] = -1;
   }

   // This loop either breaks or runs forever... In some iterations
   // At this point K is as was passed as parameter
   for(auto it : adjacency)
   {
        if(it.second == 0){
            if(it.first->COLOR != -1)
            {
                colors[it.first->COLOR] = 1;
            }
        }
    }
    // At this point K is decreased

    for(int i = 0; i < Ko; i++)
    {
        if(colors[i] == -1) { return i; }
    }

    return -1;
}

По-видимому, удаление модификации массива

colors[(*it).first->COLOR] = 1;

устраняет проблему с бесконечным циклом (к сожалению, также отменяет алгоритм, так что это не решение). Кроме того, кажется, что эта строка каким-то образом уменьшает целое число K.

Здесь выполняется вызов функции:

    aux->COLOR = getAvailableColor(G.K, aux->ADJC);

Где aux - это REG *, а ADJC - это список (REG *,целое). Структура REG:

typedef struct REG{
    int ID;
    int TYPE; // 0 - Physical, 1 - Virtual
    int COLOR;
    int CONN;
    std::list<INTERF> INTRFR;
    std::list<std::pair<REG*, int>> ADJC;

    bool operator > (const REG& reg) const { return (CONN > reg.CONN);        }
    bool operator < (const REG& reg) const { return (CONN < reg.CONN); }
    bool operator == (const REG& reg) const { return (ID == reg.ID); }
}REG;

INTERF typedef равен std :: pair (int, int), а функция, которая создает список:

void setAdjacency(GRAPH g)
{
    std::list<REG*>::iterator it;       
    std::list<INTERF>::iterator it2;     
    std::list<REG*>::iterator it3 ;      
    REG* aux = newReg(-1, -1, " ");
    REG* aux2;                           
    int count;

    for(it = g.LOGREG.begin(); it != g.LOGREG.end(); it++)
    {
        count = 0;
        (*it)->ADJC.clear();

        for(it2 = (*it)->INTRFR.begin(); it2 != (*it)->INTRFR.end(); it2++)
        {
            count++;
            aux2 = getRegister(g.REGISTERS, it2->first);

           (*it)->ADJC.insert((*it)->ADJC.end(), std::pair<REG*, int>(aux2, 0));
        }

        (*it)->CONN = count;
    }
}

Когда я останавливаю бесконечноеloop это вывод valgrind:

==13369== Process terminating with default action of signal 2 (SIGINT)
==13369==    at 0x10D008: __gnu_cxx::__aligned_membuf<std::pair<REG*, int> >::_M_ptr()
==13369==    by 0x10C67B: std::_List_node<std::pair<REG*, int> >::_M_valptr()
==13369==    by 0x10BD18: std::_List_iterator<std::pair<REG*, int> >::operator*() const
==13369==    by 0x10B116: getAvailableColor(int, std::__cxx11::list<std::pair<REG*, int>, std::allocator<std::pair<REG*, int> > >)

И недопустимая ошибка чтения:

==13520== Invalid read of size 8
==13520==    at 0x10BFE3: std::_List_iterator<std::pair<REG*, int> >::operator++()
==13520==    by 0x10B159: getAvailableColor(int, std::__cxx11::list<std::pair<REG*, int>, std::allocator<std::pair<REG*, int> > >) 
==13520==    by 0x10AE10: runStack(GRAPH) 
==13520==    by 0x10A500: algorithm(GRAPH)
==13520==    by 0x1107AC: main 
==13520==  Address 0x10520fb40 is not stack'd, malloc'd or (recently) free'd
==13520== 
==13520== 
==13520== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==13520==  Access not within mapped region at address 0x10520FB40
==13520==    at 0x10BFE3: std::_List_iterator<std::pair<REG*, int> >::operator++()
==13520==    by 0x10B159: getAvailableColor(int, std::__cxx11::list<std::pair<REG*, int>, std::allocator<std::pair<REG*, int> > >)

Буду признателен за любую помощь! Это моя первая настоящая попытка в C ++, и я уверен, что есть много чего я не понимаю в структурах.

РЕДАКТИРОВАТЬ: Использование auto, как было предложено, как минимум, имеет смыслостановил бесконечный цикл в первом тесте. Когда я сделал это, я также заметил, что значение K менялось между до и после цикла. Создание «резервной» переменной решило это. Тем не менее, в некоторых тестах по-прежнему возникают недопустимая ошибка чтения и бесконечный цикл (одна и та же структура, только разные входы). Соответствующее обновление приведено выше.

EDIT2 (решено): Был решен бесконечный цикл с заменой массива на вектор, и недопустимая ошибка чтения была проблемой логики реализации (K уменьшалось при каждомитерации, так что, хотя изначально COLOR был только такой же большой, как K-1, каждая из которых была большим переполнением). Большое спасибо всем :) 1040 *

1 Ответ

3 голосов
/ 24 октября 2019

Код итератора не выглядит особенно неправильным.

Убедитесь, что вы не обращаетесь к массиву за пределами этой инструкции:
colors[(*it).first->COLOR] = 1;
Этонаиболее вероятная причина вашей проблемы.

Однако, поскольку вы не модифицируете итератор и не обращаетесь к нему вне цикла, я бы посоветовал вам использовать расширенный синтаксис цикла for. Вместо: for(it = adjacency.begin(); it != adjacency.end(); it++)
Вы можете легко заменить на:
for (auto it: adjacency)
Если вы не должны быть совместимы с C ++ 03. Это избавит вас от ряда глупых ошибок.

...