From d347415aee61d6509240719e540c2423614ffff1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 21 Jan 2016 11:36:37 +0100 Subject: [PATCH] - fixed some garbage collection issues with interpolations: * FInterpolator depended on external references to prevent its content from getting GC'd. * none of the pointers in the interpolation objects were declared to the GC. The result of these issues was that changing anything about the life cycle of interpolation objects caused corrupted memory crashes when a level was changed. --- src/dobject.h | 5 +++++ src/dobjgc.cpp | 1 + src/p_setup.cpp | 2 +- src/r_data/r_interpolate.cpp | 32 +++++++++++++++++++++----------- src/r_data/r_interpolate.h | 7 ++++--- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 40b47ee5c5..74371c0d63 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -203,6 +203,11 @@ private: \ #define IMPLEMENT_ABSTRACT_CLASS(cls) \ _IMP_PCLASS(cls,NULL,NULL) +#define IMPLEMENT_ABSTRACT_POINTY_CLASS(cls) \ + _IMP_PCLASS(cls,cls::PointerOffsets,NULL) \ + const size_t cls::PointerOffsets[] = { + + enum EObjectFlags { // GC flags diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 3812c0b08c..2efb5a15e0 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -335,6 +335,7 @@ static void MarkRoot() SectorMarker->SecNum = 0; } Mark(SectorMarker); + Mark(interpolator.Head); // Mark bot stuff. Mark(bglobal.firstthing); Mark(bglobal.body1); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 3749e97aae..c915c31ecb 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3353,6 +3353,7 @@ extern polyblock_t **PolyBlockMap; void P_FreeLevelData () { + interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. Renderer->CleanLevelData(); FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process. SN_StopAllSequences (); @@ -3584,7 +3585,6 @@ void P_SetupLevel (const char *lumpname, int position) // Free all level data from the previous map P_FreeLevelData (); - interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. MapData *map = P_OpenMapData(lumpname, true); if (map == NULL) diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index 3ca3b557cf..268dd4aa0d 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -157,7 +157,10 @@ public: // //========================================================================== -IMPLEMENT_ABSTRACT_CLASS(DInterpolation) +IMPLEMENT_ABSTRACT_POINTY_CLASS(DInterpolation) +DECLARE_POINTER(Next) +DECLARE_POINTER(Prev) +END_POINTERS IMPLEMENT_CLASS(DSectorPlaneInterpolation) IMPLEMENT_CLASS(DSectorScrollInterpolation) IMPLEMENT_CLASS(DWallScrollInterpolation) @@ -213,9 +216,9 @@ void FInterpolator::UpdateInterpolations() void FInterpolator::AddInterpolation(DInterpolation *interp) { interp->Next = Head; - if (Head != NULL) Head->Prev = &interp->Next; + if (Head != NULL) Head->Prev = interp; + interp->Prev = NULL; Head = interp; - interp->Prev = &Head; count++; } @@ -227,14 +230,19 @@ void FInterpolator::AddInterpolation(DInterpolation *interp) void FInterpolator::RemoveInterpolation(DInterpolation *interp) { - if (interp->Prev != NULL) + if (Head == interp) { - *interp->Prev = interp->Next; - if (interp->Next != NULL) interp->Next->Prev = interp->Prev; - interp->Next = NULL; - interp->Prev = NULL; - count--; + Head = interp->Next; + if (Head != NULL) Head->Prev = NULL; } + else + { + if (interp->Prev != NULL) interp->Prev->Next = interp->Next; + if (interp->Next != NULL) interp->Next->Prev = interp->Prev; + } + interp->Next = NULL; + interp->Prev = NULL; + count--; } //========================================================================== @@ -285,13 +293,15 @@ void FInterpolator::RestoreInterpolations() void FInterpolator::ClearInterpolations() { - for (DInterpolation *probe = Head; probe != NULL; ) + DInterpolation *probe = Head; + Head = NULL; + while (probe != NULL) { DInterpolation *next = probe->Next; + probe->Next = probe->Prev = NULL; probe->Destroy(); probe = next; } - Head = NULL; } diff --git a/src/r_data/r_interpolate.h b/src/r_data/r_interpolate.h index bbd2438d87..9f28b04d08 100644 --- a/src/r_data/r_interpolate.h +++ b/src/r_data/r_interpolate.h @@ -13,9 +13,10 @@ class DInterpolation : public DObject friend struct FInterpolator; DECLARE_ABSTRACT_CLASS(DInterpolation, DObject) + HAS_OBJECT_POINTERS - DInterpolation *Next; - DInterpolation **Prev; + TObjPtr Next; + TObjPtr Prev; int refcount; protected: @@ -40,7 +41,7 @@ public: struct FInterpolator { - DInterpolation *Head; + TObjPtr Head; bool didInterp; int count;