Avoids iterator invalidation in QwtPlot item lists

When working with a summary ensemble in a Debug build on Windows, a crash happened in RiuQwtPlotWidget::resetPlotCurveHighlighting(). When iterating over list of plot items, one pointer to item pointed to 0xddddddd, a clear indication that the underlying list had been updated during the loop and the iterator invalidated.

The change ensures that modifications to the item list during iteration do not cause unexpected behavior, particularly in scenarios involving grid lines and curve highlighting.

This is achieved by making a copy of the item list before iteration when modifications may occur. For cases where no add/remove will be performed during the iteration, a comment is added to clarify that it is safe to access the reference to the list.
This commit is contained in:
Magne Sjaastad committed 2025-11-10 14:58:55 +01:00
1 parent 29335a5e0e
commit 626d68ec59
6 files changed
+14 -2

No files matched your search

@@ -710,6 +710,7 @@ void RiuGroupedBarChartBuilder::addBarChartToPlot( QwtPlot* plot, Qt::Orientatio
// Get or create the two grids used in the plot
{
// Ok to access reference to list, no add/remove of item during iteration
QwtPlotItemList gridList = plot->itemList( QwtPlotItem::Rtti_PlotGrid );
for ( QwtPlotItem* plItem : gridList )
{
@@ -424,6 +424,7 @@ const QwtPlotCurve* RiuPvtPlotWidget::closestCurveSample( const QPoint& cursorPo
double distMin = HUGE_VAL;
int closestPointSampleIndex = -1;
// Ok to access reference to list, no add/remove of item during iteration
const QwtPlotItemList& itemList = m_qwtPlot->itemList();
for ( QwtPlotItemIterator it = itemList.begin(); it != itemList.end(); it++ )
{
@@ -146,6 +146,7 @@ QPointF RiuQwtCurvePointTracker::closestCurvePoint( const QPoint& cursorPosition
double distMin = DBL_MAX;
int closestPointSampleIndex = -1;
// Ok to access reference to list, no add/remove of item during iteration
const QwtPlotItemList& itmList = m_plot->itemList();
for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); it++ )
{
@@ -325,6 +325,7 @@ QList<QwtLegendData> RiuQwtPlotTools::createLegendData( const std::vector<RimPlo
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotTools::enableGridLines( QwtPlot* plot, QwtAxis::Position axis, bool enableMajor, bool enableMinor )
{
// NB: Make a copy, not reference to avoid iterator invalidation
QwtPlotItemList plotItems = plot->itemList( QwtPlotItem::Rtti_PlotGrid );
for ( QwtPlotItem* plotItem : plotItems )
{
@@ -349,6 +349,7 @@ void RiuQwtPlotWidget::setAxisLabelsAndTicksEnabled( RiuPlotAxis axis, bool enab
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::enableGridLines( RiuPlotAxis axis, bool majorGridLines, bool minorGridLines )
{
// NB: Make a copy, not reference to avoid iterator invalidation
QwtPlotItemList plotItems = m_plot->itemList( QwtPlotItem::Rtti_PlotGrid );
auto qwtAxis = toQwtPlotAxis( axis );
for ( QwtPlotItem* plotItem : plotItems )
@@ -893,6 +894,7 @@ void RiuQwtPlotWidget::findClosestPlotItem( const QPoint& pos, QwtPlotItem** clo
*closestCurveSampleIndex = -1;
*distanceFromClick = std::numeric_limits<double>::infinity();
// Ok to access reference to list, no add/remove of item during iteration
const QwtPlotItemList& itmList = m_plot->itemList();
for ( auto it : itmList )
{
@@ -1109,6 +1111,7 @@ void RiuQwtPlotWidget::highlightPlotCurves( const std::vector<RimPlotCurve*>& cu
return;
}
// NB: Make a copy, not reference to avoid iterator invalidation
auto plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList )
{
@@ -1190,6 +1193,7 @@ void RiuQwtPlotWidget::highlightPlotCurves( const std::vector<RimPlotCurve*>& cu
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::highlightPlotShapeItems( const std::set<const QwtPlotItem*>& closestItems )
{
// NB: Make a copy, not reference to avoid iterator invalidation
auto plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList )
{
@@ -1238,7 +1242,8 @@ void RiuQwtPlotWidget::resetPlotCurveHighlighting()
return;
}
const auto& plotItemList = m_plot->itemList();
// NB: Make a copy, not reference to avoid iterator invalidation
const QwtPlotItemList plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList )
{
if ( auto* riuPlotCurve = dynamic_cast<RiuQwtPlotCurve*>( plotItem ) )
@@ -1260,7 +1265,8 @@ void RiuQwtPlotWidget::resetPlotCurveHighlighting()
//--------------------------------------------------------------------------------------------------
void RiuQwtPlotWidget::resetPlotShapeItemHighlighting()
{
const auto& plotItemList = m_plot->itemList();
// NB: Make a copy, not reference to avoid iterator invalidation
const QwtPlotItemList plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList )
{
auto* plotShapeItem = dynamic_cast<QwtPlotShapeItem*>( plotItem );
@@ -1312,6 +1318,7 @@ void RiuQwtPlotWidget::highlightPlotItemsForQwtAxis( QwtAxisId axisId )
{
std::vector<RimPlotCurve*> curves;
// NB: Make a copy, not reference to avoid iterator invalidation
auto plotItemList = m_plot->itemList();
for ( QwtPlotItem* plotItem : plotItemList )
{