Defer ghost deallocation til FreeGhosts

Fixes KartKrew/Kart#824

The for-loop attempts to read `g` after the object it points to has
already been freed by Z_Free. Instead, we add a new `done` field, and
mark it when hitting the end of the demo, and skip ghosts in the ghost
list which have it set.
This commit is contained in:
Eidolon 2024-01-02 15:26:51 -06:00 committed by NepDisk
parent 061c98a7d2
commit f9c231a77c
2 changed files with 9 additions and 5 deletions

View file

@ -1111,7 +1111,7 @@ void G_ConsGhostTic(INT32 playernum)
void G_GhostTicker(void)
{
demoghost *g,*p;
for(g = ghosts, p = NULL; g; g = g->next)
for (g = ghosts, p = NULL; g; g = g->next)
{
// Skip normal demo data.
UINT16 ziptic = READUINT8(g->p);
@ -1138,7 +1138,9 @@ void G_GhostTicker(void)
else if (ziptic == DW_RNG)
g->p += 4; // RNG seed
else
I_Error("Ghost is not a record attack ghost DXD"); //@TODO lmao don't blow up like this
{
I_Error("Ghost is not a record attack ghost DXD (ziptic = %u)", ziptic); //@TODO lmao don't blow up like this
}
ziptic = READUINT8(g->p);
}
@ -1382,11 +1384,11 @@ skippedghosttic:
if (follow)
follow->fuse = TICRATE;
#endif
g->done = true;
if (p)
{
p->next = g->next;
else
ghosts = g->next;
Z_Free(g);
}
continue;
}

View file

@ -159,6 +159,8 @@ struct demoghost {
UINT8 *buffer, *p, color;
UINT8 fadein;
UINT16 version;
boolean linecrossed;
boolean done;
mobj_t oldmo, *mo;
struct demoghost *next;
};