diff --git a/docs/changelog.txt b/docs/changelog.txt index 7269a120d2..795d531583 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -65,6 +65,7 @@ Template for new versions: - ``Units::getReadableName``: correct display of ghost+curse names w/r/t each other and unit prof, use ``curse.name`` instead of iterating syndrome name effects - `autodump`: cancel active job on dumped items - `add-spatter`: fix a crash related to unloading a savegame with add-spatter reactions, then loading a second savegame with add-spatter reactions +- adjust semantics of vmethod interpose maps to avoid inserting null pointers ## Misc Improvements - `tweak`: improve performance of ``adamantine-cloth-wear`` tweak diff --git a/library/VTableInterpose.cpp b/library/VTableInterpose.cpp index 9522cb2405..2bcfac7ff9 100644 --- a/library/VTableInterpose.cpp +++ b/library/VTableInterpose.cpp @@ -400,7 +400,7 @@ void VMethodInterposeLinkBase::on_host_delete(const virtual_identity *from) { // Otherwise, drop the link to that child: assert(child_hosts.count(from) != 0 && - from->interpose_list[vmethod_idx] == this); + from->interpose_list[vmethod_idx] == this); // while mutating this gets cleaned up below so machts nichts // Find and restore the original vmethod ptr auto last = this; @@ -412,7 +412,7 @@ void VMethodInterposeLinkBase::on_host_delete(const virtual_identity *from) // Unlink the chains child_hosts.erase(from); - from->interpose_list[vmethod_idx] = NULL; + from->interpose_list.erase(vmethod_idx); } } @@ -434,8 +434,10 @@ bool VMethodInterposeLinkBase::apply(bool enable) } // Retrieve the current vtable entry - VMethodInterposeLinkBase *old_link = host->interpose_list[vmethod_idx]; - VMethodInterposeLinkBase *next_link = NULL; + auto l = host->interpose_list.find(vmethod_idx); + + VMethodInterposeLinkBase* old_link = (l != host->interpose_list.end()) ? (l->second) : nullptr; + VMethodInterposeLinkBase* next_link = NULL; while (old_link && old_link->host == host && old_link->priority > priority) { @@ -529,7 +531,7 @@ bool VMethodInterposeLinkBase::apply(bool enable) for (auto it = child_hosts.begin(); it != child_hosts.end(); ++it) { auto nhost = *it; - assert(nhost->interpose_list[vmethod_idx] == old_link); + assert(nhost->interpose_list[vmethod_idx] == old_link); // acceptable due to assign below nhost->set_vmethod_ptr(patcher, vmethod_idx, interpose_method); nhost->interpose_list[vmethod_idx] = this; } @@ -586,7 +588,7 @@ void VMethodInterposeLinkBase::remove() for (auto it = child_hosts.begin(); it != child_hosts.end(); ++it) { auto nhost = *it; - assert(nhost->interpose_list[vmethod_idx] == this); + assert(nhost->interpose_list[vmethod_idx] == this); // acceptable due to assign below nhost->interpose_list[vmethod_idx] = prev; nhost->set_vmethod_ptr(patcher, vmethod_idx, saved_chain); if (prev)