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 40b47ee5c..74371c0d6 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 3812c0b08..2efb5a15e 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 3749e97aa..c915c31ec 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 3ca3b557c..268dd4aa0 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 bbd2438d8..9f28b04d0 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;