Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Missing increment of index in foreach with QMap



  • Hello,

    Since we updated from VS 16.3.10 to 16.5.4 we had some failures in our unittest. We were able to track them down to an old usage of QMap in a foreach.

    In the example code below the rowNr variable is not incremented at all in release mode. In debug it is. Optimisation level is set to /O2.

    When yo uncomment the last logging line the counter is incremented.

    Has anybody a clue whether this is a bug in Qt?

    The funny thing is ist does not happen with the stringlist so it has something to do with the foreach + QMap.

    And yes: There are better ways to iterate over a QMap.

        QMap <QString, QString> mapContainer;
        mapContainer.insert (QString ("One"), QString ("1"));
        mapContainer.insert (QString ("Two"), QString ("2"));
        mapContainer.insert (QString ("Three"), QString ("3"));
        mapContainer.insert (QString ("Four"), QString ("4"));
        mapContainer.insert (QString ("Five"), QString ("5"));
    
        //QStringList mapContainer = { QString ("One"), QString ("Two"), QString ("Three"), QString ("Four"), QString ("Five") };
    
        unsigned int rowNr = 0;
    
        foreach (QString contour, mapContainer)
        //for (unsigned int secondLoopIndex = 0; secondLoopIndex < 5; ++secondLoopIndex)
        {
    
          LOGINFO (QString ("<-----------------------Index row in loop before incr.: (%1)").arg (rowNr));
          ++rowNr;
          //LOGINFO (QString ("<-----------------------Index row in loop after incr.: (%1)").arg (rowNr));
        }
    

    Output

    <-----------------------Index row in loop before incr.: (0)
    <-----------------------Index row in loop before incr.: (0)
    <-----------------------Index row in loop before incr.: (0)
    <-----------------------Index row in loop before incr.: (0)
    <-----------------------Index row in loop before incr.: (0)
    


  • And it helps to not put the increment (++rowNr) at the end of the for loop (without direct usage) but at the beginning prior to its usage.

    So it seems related to some optimisation.


  • Lifetime Qt Champion

    Please provide a minimal compilable example so we can test you code. This code is working fine:

    int main(int argc, char **argv)
    {
      QApplication app(argc, argv);
    
      QMap <QString, QString> mapContainer;
      mapContainer.insert (QString ("One"), QString ("1"));
      mapContainer.insert (QString ("Two"), QString ("2"));
      mapContainer.insert (QString ("Three"), QString ("3"));
      mapContainer.insert (QString ("Four"), QString ("4"));
      mapContainer.insert (QString ("Five"), QString ("5"));
    
      unsigned int rowNr = 0;
      foreach (QString contour, mapContainer)
        //for (unsigned int secondLoopIndex = 0; secondLoopIndex < 5; ++secondLoopIndex)
      {
        qDebug() << QString ("<-----------------------Index row in loop before incr.: (%1)").arg (rowNr);
        ++rowNr;
        qDebug() << QString ("<-----------------------Index row in loop after incr.: (%1)").arg (rowNr);
      }
    
      return app.exec();
    }
    

  • Qt Champions 2017

    @EMStegehuis said in Missing increment of index in foreach with QMap:

    Has anybody a clue whether this is a bug in Qt?

    Probably not. Compile in release with debug info and inspect the assembly, probably an optimizer problem. Whatever the reason, however, you should move to a range-based for, foreach's deprecated.


Log in to reply