[Bugfix] GridLayer::parent_grid is a dangling raw pointer when grid is destroyed #270
Labels
No labels
Alpha Release Requirement
Bugfix
Demo Target
Documentation
Major Feature
Minor Feature
priority:tier1-active
priority:tier2-foundation
priority:tier3-future
priority:tier4-deferred
Refactoring & Cleanup
system:animation
system:documentation
system:grid
system:input
system:performance
system:procgen
system:python-binding
system:rendering
system:ui-hierarchy
Tiny Feature
workflow:blocked
workflow:needs-benchmark
workflow:needs-documentation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Depends on
#252
GridView and Grid, FOVLayer and PathLayer
john/McRogueFace
Reference
john/McRogueFace#270
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
GridLayerstores its parent grid as a rawUIGrid*pointer (GridLayers.h:34). When the owning grid is destroyed, this pointer is not automatically nullified. If a Python-side reference to the layer outlives the grid, any method that accessesparent_griddereferences freed memory.Root Cause
GridLayers.h:34:This raw pointer is used extensively in
GridLayers.cpp:parent_grid->computeFOV()parent_grid->isInFOV()parent_grid->fov_radiusWhile some access points check
if (!parent_grid), the pointer itself becomes dangling (non-NULL but invalid) when the grid is destroyed — the check passes but the dereference is UB.Reproduction
Note: The grid setter code (
GridLayers.cpp:1624, 2259) does checkif (!self->data->parent_grid), but a dangling pointer won't be NULL — it will appear valid and dereference freed memory.Fix Options
std::shared_ptr<UIGrid>: Keeps grid alive while layers reference it — but creates ownership issues since grid owns layersstd::weak_ptr<UIGrid>: Best option. Grid stays as owner, layers hold weak references. Check.lock()before access.parent_grid = nullptr. Requires tracking.Option 2 (weak_ptr) is cleanest: it mirrors the pattern already used by
PyUniformCollectionObject::owner.Severity
Medium — requires grid to be destroyed while layer references exist. Currently uncommon in practice because grids tend to live longer than their layers, but becomes important with dynamic scene management.
GridViewandGrid,FOVLayerandPathLayerDeferred from the #258–#278 memory safety audit. The raw
UIGrid*pointer issue is naturally resolved by #252 (GridMap/GridView split), which replacesUIGridentirely. GridLayer::parent_grid will change fromUIGrid*toGridMap*with proper lifetime management as part of that architecture change. Linked as dependency of #252.GridViewandGrid,FOVLayerandPathLayer#252Roadmap context
Folded into #252 (Grid/GridView split) in the Grid & Entity Overhaul Roadmap (
docs/GRID_ENTITY_OVERHAUL_ROADMAP.md), Phase 4. During the split, all rawUIGrid*pointers in GridLayer, UIGridPoint, and GridChunk will be converted toweak_ptr<Grid>.GridViewandGrid,FOVLayerandPathLayer#252