From 159e1784f4bae7e65122cfdf288afc4842f61651 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 18 May 2019 18:44:06 +0200 Subject: [PATCH] Memory leak in RefreshMapper, fixes #5323 --- rtgui/eventmapper.cc | 23 +++++++++++++++-------- rtgui/eventmapper.h | 2 ++ rtgui/history.cc | 35 +++++++++++++++-------------------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/rtgui/eventmapper.cc b/rtgui/eventmapper.cc index de5258413..81160c58e 100644 --- a/rtgui/eventmapper.cc +++ b/rtgui/eventmapper.cc @@ -19,12 +19,13 @@ */ #include "eventmapper.h" +#include "multilangmgr.h" ProcEventMapper::ProcEventMapper() { for (int event = 0; event < rtengine::NUMOFEVENTS; ++event) { - history_msgs_[event] = "HISTORY_MSG_" + std::to_string(event + 1); + history_msgs_[event] = M("HISTORY_MSG_" + std::to_string(event + 1)); } } @@ -38,16 +39,22 @@ ProcEventMapper *ProcEventMapper::getInstance() rtengine::ProcEvent ProcEventMapper::newEvent(int action, const std::string &history_msg) { - rtengine::ProcEvent event = rtengine::RefreshMapper::getInstance()->newEvent(); - rtengine::RefreshMapper::getInstance()->mapEvent(event, action); + std::string eventkey = std::to_string(action) + history_msg; + const auto ret = events_.find(eventkey); + if (ret == events_.end()) { + rtengine::ProcEvent event = rtengine::RefreshMapper::getInstance()->newEvent(); + rtengine::RefreshMapper::getInstance()->mapEvent(event, action); + events_.emplace(std::move(eventkey), event); + if (history_msg.empty()) { + history_msgs_[event] = M("HISTORY_MSG_" + std::to_string(event + 1)); + } else { + history_msgs_[event] = M(history_msg); + } - if (history_msg.empty()) { - history_msgs_[event] = "HISTORY_MSG_" + std::to_string(event + 1); + return event; } else { - history_msgs_[event] = history_msg; + return ret->second; } - - return event; } diff --git a/rtgui/eventmapper.h b/rtgui/eventmapper.h index 87ccc1d9b..f977b0ff4 100644 --- a/rtgui/eventmapper.h +++ b/rtgui/eventmapper.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include "../rtengine/refreshmap.h" @@ -34,4 +35,5 @@ private: ProcEventMapper(); std::unordered_map history_msgs_; + std::map events_; }; diff --git a/rtgui/history.cc b/rtgui/history.cc index 4d435c460..ec5e006bc 100644 --- a/rtgui/history.cc +++ b/rtgui/history.cc @@ -225,15 +225,14 @@ void History::procParamsChanged( return; } - selchangehist.block (true); - selchangebm.block (true); + selchangehist.block(true); + selchangebm.block(true); if (ev == EvPhotoLoaded) { - initHistory (); + initHistory(); } // construct formatted list content - Glib::ustring text = M(ProcEventMapper::getInstance()->getHistoryMsg(ev)); Glib::RefPtr selection = hTreeView->get_selection(); Gtk::TreeModel::iterator iter = selection->get_selected(); @@ -243,12 +242,12 @@ void History::procParamsChanged( ++iter; while (iter) { - iter = historyModel->erase (iter); + iter = historyModel->erase(iter); } } // lookup the last remaining item in the list - int size = historyModel->children().size (); + const int size = historyModel->children().size(); Gtk::TreeModel::Row row; if (size > 0) { @@ -258,47 +257,43 @@ void History::procParamsChanged( // if there is no last item or its chev!=ev, create a new one if (size == 0 || !row || row[historyColumns.chev] != ev || ev == EvProfileChanged) { Gtk::TreeModel::Row newrow = *(historyModel->append()); - newrow[historyColumns.text] = text; + newrow[historyColumns.text] = ProcEventMapper::getInstance()->getHistoryMsg(ev); newrow[historyColumns.value] = g_markup_escape_text(descr.c_str(), -1); newrow[historyColumns.chev] = ev; newrow[historyColumns.params] = *params; newrow[historyColumns.paramsEdited] = paramsEdited ? *paramsEdited : defParamsEdited; if (ev != EvBookmarkSelected) { - selection->select (newrow); + selection->select(newrow); } if (blistener && row && !blistenerLock) { - blistener->historyBeforeLineChanged (row[historyColumns.params]); + blistener->historyBeforeLineChanged(row[historyColumns.params]); } else if (blistener && size == 0 && !blistenerLock) { - blistener->historyBeforeLineChanged (newrow[historyColumns.params]); + blistener->historyBeforeLineChanged(newrow[historyColumns.params]); } - } - // else just update it - else { - row[historyColumns.text] = text; + } else { // else just update it row[historyColumns.value] = g_markup_escape_text(descr.c_str(), -1); - row[historyColumns.chev] = ev; row[historyColumns.params] = *params; row[historyColumns.paramsEdited] = paramsEdited ? *paramsEdited : defParamsEdited; if (ev != EvBookmarkSelected) { - selection->select (row); + selection->select(row); } } if (ev != EvBookmarkSelected) { - bTreeView->get_selection()->unselect_all (); + bTreeView->get_selection()->unselect_all(); } if (!selection->get_selected_rows().empty()) { std::vector selp = selection->get_selected_rows(); - hTreeView->scroll_to_row (*selp.begin()); + hTreeView->scroll_to_row(*selp.begin()); } - selchangehist.block (false); - selchangebm.block (false); + selchangehist.block(false); + selchangebm.block(false); } void History::clearParamChanges ()