From cb12a59eed0370ca00eca909b65a34d1c578ebee Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Tue, 5 Aug 2025 20:14:55 +0100 Subject: [PATCH] Fix #14495: Dangling references in Industry Production graph window. (#14496) --- src/graph_gui.cpp | 24 +++++++++--------------- src/misc/history_func.hpp | 15 +++++++++++---- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index d3fd85343c..0240b28ba7 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -253,9 +253,7 @@ protected: template struct Filler : BaseFiller { - const Tprojection &proj; ///< Projection to apply. - - constexpr Filler(DataSet &dataset, const Tprojection &proj) : BaseFiller(dataset), proj(proj) {} + Tprojection proj; ///< Projection to apply. inline void Fill(uint i, const auto &data) const { this->dataset.values[i] = std::invoke(this->proj, data); } }; @@ -1776,16 +1774,16 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow { produced.colour = cs->legend_colour; produced.exclude_bit = cs->Index(); produced.range_bit = 0; - auto produced_filler = Filler{produced, &Industry::ProducedHistory::production}; DataSet &transported = this->data.emplace_back(); transported.colour = cs->legend_colour; transported.exclude_bit = cs->Index(); transported.range_bit = 1; transported.dash = 2; - auto transported_filler = Filler{transported, &Industry::ProducedHistory::transported}; - FillFromHistory(p.history, i->valid_history, *this->scales[this->selected_scale].history_range, produced_filler, transported_filler); + FillFromHistory(p.history, i->valid_history, *this->scales[this->selected_scale].history_range, + Filler{{produced}, &Industry::ProducedHistory::production}, + Filler{{transported}, &Industry::ProducedHistory::transported}); } for (const auto &a : i->accepted) { @@ -1799,20 +1797,16 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow { accepted.exclude_bit = cs->Index(); accepted.range_bit = 2; accepted.dash = 1; - auto accepted_filler = Filler{accepted, &Industry::AcceptedHistory::accepted}; DataSet &waiting = this->data.emplace_back(); waiting.colour = cs->legend_colour; waiting.exclude_bit = cs->Index(); waiting.range_bit = 3; waiting.dash = 4; - auto waiting_filler = Filler{waiting, &Industry::AcceptedHistory::waiting}; - if (a.history == nullptr) { - FillFromEmpty(i->valid_history, *this->scales[this->selected_scale].history_range, accepted_filler, waiting_filler); - } else { - FillFromHistory(*a.history, i->valid_history, *this->scales[this->selected_scale].history_range, accepted_filler, waiting_filler); - } + FillFromHistory(a.history.get(), i->valid_history, *this->scales[this->selected_scale].history_range, + Filler{{accepted}, &Industry::AcceptedHistory::accepted}, + Filler{{waiting}, &Industry::AcceptedHistory::waiting}); } this->SetDirty(); @@ -1955,8 +1949,8 @@ struct TownCargoGraphWindow : BaseCargoGraphWindow { transported.dash = 2; FillFromHistory(s.history, t->valid_history, *this->scales[this->selected_scale].history_range, - Filler{produced, &Town::SuppliedHistory::production}, - Filler{transported, &Town::SuppliedHistory::transported}); + Filler{{produced}, &Town::SuppliedHistory::production}, + Filler{{transported}, &Town::SuppliedHistory::transported}); } this->SetDirty(); diff --git a/src/misc/history_func.hpp b/src/misc/history_func.hpp index b9cf383d2a..b143fb4bdc 100644 --- a/src/misc/history_func.hpp +++ b/src/misc/history_func.hpp @@ -116,7 +116,7 @@ bool GetHistory(const HistoryData &history, ValidHistoryMask valid_history, c * @param fillers Fillers to fill with history data. */ template -void FillFromHistory(const HistoryData &history, ValidHistoryMask valid_history, const HistoryRange &hr, Tfillers... fillers) +void FillFromHistory(const HistoryData &history, ValidHistoryMask valid_history, const HistoryRange &hr, Tfillers &&... fillers) { T result{}; for (uint i = 0; i != N; ++i) { @@ -129,14 +129,21 @@ void FillFromHistory(const HistoryData &history, ValidHistoryMask valid_histo } /** - * Fill some data with empty records. + * Fill some data with optional historical data. + * @param history Historical data to fill from, or nullptr if not present. * @param valid_history Mask of valid history records. * @param hr History range to fill with. * @param fillers Fillers to fill with history data. */ -template -void FillFromEmpty(ValidHistoryMask valid_history, const HistoryRange &hr, Tfillers... fillers) +template +void FillFromHistory(const HistoryData *history, ValidHistoryMask valid_history, const HistoryRange &hr, Tfillers &&... fillers) { + if (history != nullptr) { + FillFromHistory(*history, valid_history, hr, std::forward(fillers)...); + return; + } + + /* History isn't present, fill zero or invalid instead. */ for (uint i = 0; i != N; ++i) { if (IsValidHistory(valid_history, hr, N - i - 1)) { (fillers.MakeZero(i), ...);