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.
This commit is contained in:
couriersud 2019-02-09 23:06:01 +01:00
parent 9d8cb783e3
commit 83bd138bec
5 changed files with 30 additions and 24 deletions

View File

@ -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 */

View File

@ -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<net_t *, netlist_time>;
explicit queue_t(netlist_state_t &nl);
~queue_t();
protected:
@ -1249,7 +1250,7 @@ namespace netlist
std::unique_ptr<callbacks_t> &&callbacks,
std::unique_ptr<setup_t> &&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;
}

View File

@ -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

View File

@ -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++;
}
}

View File

@ -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<const entry_t *> save_list() const
{
std::vector<const entry_t *> 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);