From 83bd138bec869d9d3b78620d7de756763ca2b0cd Mon Sep 17 00:00:00 2001 From: couriersud Date: Sat, 9 Feb 2019 23:06:01 +0100 Subject: [PATCH] netlist: Fix crashes on certain hardware/library combos. (nw) At least on macosx memory used by an object seems to be invalidated before the dtor is executed. This of course is deadly for child objects with references to the parent-in-deletion which may call back into the parent. One of the worst issues I had to fix. Ever. Lesson learnt: No tricks in dtors. Never. --- src/lib/netlist/nl_base.cpp | 19 ++++--------------- src/lib/netlist/nl_base.h | 14 ++++++++++++-- src/lib/netlist/nl_setup.cpp | 1 + src/lib/netlist/plib/pstate.cpp | 12 ++++++------ src/lib/netlist/plib/pstate.h | 8 +++++++- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index d55e75df6fb..246077788d9 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -148,6 +148,10 @@ detail::queue_t::queue_t(netlist_state_t &nl) { } +detail::queue_t::~queue_t() +{ +} + void detail::queue_t::register_state(plib::state_manager_t &manager, const pstring &module) { //state().log().debug("register_state\n"); @@ -268,15 +272,6 @@ netlist_state_t::netlist_state_t(const pstring &aname, } -netlist_state_t::~netlist_state_t() -{ - nets().clear(); - m_devices.clear(); -} - - - - void netlist_t::stop() { log().debug("Printing statistics ...\n"); @@ -695,12 +690,6 @@ detail::net_t::net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t { } -detail::net_t::~net_t() -{ - state().run_state_manager().remove_save_items(this); -} - - void detail::net_t::rebuild_list() { /* rebuild m_list */ diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index c2bf42999f3..69ace67d9d7 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -713,7 +713,7 @@ namespace netlist }; net_t(netlist_state_t &nl, const pstring &aname, core_terminal_t *mr = nullptr); - virtual ~net_t(); + virtual ~net_t() = default; void reset(); @@ -1221,6 +1221,7 @@ namespace netlist public: using entry_t = pqentry_t; explicit queue_t(netlist_state_t &nl); + ~queue_t(); protected: @@ -1249,7 +1250,7 @@ namespace netlist std::unique_ptr &&callbacks, std::unique_ptr &&setup); - ~netlist_state_t(); + ~netlist_state_t() = default; friend class netlist_t; // allow access to private members @@ -1320,11 +1321,20 @@ namespace netlist m_devices.insert(m_devices.end(), { name, std::move(dev) }); } + /** + * @brief Remove device + * + * Care needs to be applied if this is called to remove devices with + * sub-devices which may have registered state. + * + * @param dev Device to be removed + */ void remove_dev(core_device_t *dev) { for (auto it = m_devices.begin(); it != m_devices.end(); it++) if (it->second.get() == dev) { + m_state.remove_save_items(dev); m_devices.erase(it); return; } diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 2fad9ea4836..cfc9a7eb484 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -1000,6 +1000,7 @@ void setup_t::delete_empty_nets() if (x->num_cons() == 0) { x->state().log().verbose("Deleting net {1} ...", x->name()); + x->state().run_state_manager().remove_save_items(x.get()); return true; } else diff --git a/src/lib/netlist/plib/pstate.cpp b/src/lib/netlist/plib/pstate.cpp index 14d0da3d374..3bd93ed4f8e 100644 --- a/src/lib/netlist/plib/pstate.cpp +++ b/src/lib/netlist/plib/pstate.cpp @@ -18,19 +18,19 @@ void state_manager_t::save_state_ptr(const void *owner, const pstring &stname, c void state_manager_t::remove_save_items(const void *owner) { - for (auto i = m_save.begin(); i != m_save.end(); ) + auto i = m_save.end(); + while (i != m_save.begin()) { + i--; if (i->get()->m_owner == owner) i = m_save.erase(i); - else - i++; } - for (auto i = m_custom.begin(); i != m_custom.end(); ) + i = m_custom.end(); + while (i > m_custom.begin()) { + i--; if (i->get()->m_owner == owner) i = m_custom.erase(i); - else - i++; } } diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h index 2e6026f355a..290333bf87d 100644 --- a/src/lib/netlist/plib/pstate.h +++ b/src/lib/netlist/plib/pstate.h @@ -117,7 +117,13 @@ public: void post_load(); void remove_save_items(const void *owner); - const entry_t::list_t &save_list() const { return m_save; } + const std::vector save_list() const + { + std::vector ret; + for (auto &i : m_save) + ret.push_back(i.get()); + return ret; + } void save_state_ptr(const void *owner, const pstring &stname, const datatype_t &dt, const std::size_t count, void *ptr);