From 0c9c624e8cfeeff5fbd78fb1641749d34e08bff9 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 8 Oct 2013 21:32:26 -0500 Subject: [PATCH] Do not follow NextThinker links in DestroyThinkersInList - Fixed: DThinker::Destroy(Most)ThinkersInList() were unreliable when destroyed thinkers destroyed more thinkers in the same list. Specifically, if the thinker it destroyed caused the very next thinker in the list to also be destroyed, it would get lost in the thinker list and end up with a NULL node. So just keep iterating through the first thinker in the list until there are none left. Since destroying a thinker causes it to remove itself from its list, the first thinker will always be changing as long as there's something to destroy. --- src/dthinker.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 15206dabd..5405051e7 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -357,12 +357,10 @@ void DThinker::DestroyThinkersInList (FThinkerList &list) { if (list.Sentinel != NULL) { - DThinker *node = list.Sentinel->NextThinker; - while (node != list.Sentinel) + for (DThinker *node = list.Sentinel->NextThinker; node != list.Sentinel; node = list.Sentinel->NextThinker) { - DThinker *next = node->NextThinker; + assert(node != NULL); node->Destroy(); - node = next; } list.Sentinel->Destroy(); list.Sentinel = NULL; @@ -380,9 +378,8 @@ void DThinker::DestroyMostThinkersInList (FThinkerList &list, int stat) // it from the list. G_FinishTravel() will find it later from // a players[].mo link and destroy it then, after copying various // information to a new player. - for (DThinker *probe = list.Sentinel->NextThinker, *next; probe != list.Sentinel; probe = next) + for (DThinker *probe = list.Sentinel->NextThinker; probe != list.Sentinel; probe = list.Sentinel->NextThinker) { - next = probe->NextThinker; if (!probe->IsKindOf(RUNTIME_CLASS(APlayerPawn)) || // <- should not happen static_cast(probe)->player == NULL || static_cast(probe)->player->mo != probe)