用于迭代遍历列表的迭代器

时间:2019-10-24 03:18:22

标签: c++ list c++11 iterator

我在for循环中使用迭代器,由于某种原因,它无限循环。但是,它似乎正在无限地进行它应该做的事情。

看看其他类似的问题并没有帮助我解决问题,因为我没有在任何地方使用拼接,而是尝试了许多不同的方式来实现此循环(例如,将int用于条件循环,使用迭代器本身,迭代器前进等)。我获得的最大进步是获得了无效的读取(见下文)。

我仔细检查了代码,看看是否没有直接操作迭代器指针(可能会产生list.end()= list.begin()的情况),但找不到任何类似的东西。我用于此特定列表的全部是查找,插入和清除。

我正在遍历由结构指针REG和一个int组成的对的列表。这是在C ++ 11中用-Wall和-Wextra编译的。

对其进行任何修改以使其停止在最后一项(使用.size()或检查矢量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 *,int)。 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;
    }
}

当我停止无限循环时,这是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一样大,每次迭代都产生较大的溢出)。非常感谢大家:)

1 个答案:

答案 0 :(得分:3)

有关迭代器的代码看起来并不特别错误。

请确保您不会在此说明中超出范围访问数组:
colors[(*it).first->COLOR] = 1;
这是造成您问题的最可能原因。

但是,由于您没有修改迭代器,也不要在循环外访问它,所以我建议您使用增强的for循环语法。 代替: for(it = adjacency.begin(); it != adjacency.end(); it++)
您可以轻松地替换为:
for (auto it: adjacency)
除非您必须与C ++ 03兼容。 这样可以避免许多愚蠢的错误。