mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-25 06:38:13 -05:00
#14182 Fix stack overflow when destroying deep AABB bounding box trees
The bounding box tree is destroyed by deleteInternalNodesBottomUp, which recursed once per tree level. For deep or unbalanced trees this overflowed the call stack during project close (RigMainGrid destruction). Replace the recursion with an explicit stack. Deleting an internal node does not touch its children, so the child pointers are read before the node is deleted and the deletion order is irrelevant. Leaf nodes remain pooled and are not deleted individually.
This commit is contained in:
1 parent
0410635815
commit
f7ccfcfff6
1 file changed
+20
-6
@@ -793,15 +793,29 @@ cvf::AABBTreeNodeLeaf* AABBTree::createOrAssignLeaf(size_t leafIndex, const std:
|
||||
void AABBTree::deleteInternalNodesBottomUp(AABBTreeNode* node)
|
||||
{
|
||||
// All leaf nodes (AABBTreeNodeLeaf) are allocated in m_leafPool and does not require a delete
|
||||
if (node->type() == AB_LEAF) return;
|
||||
if (!node || node->type() == AB_LEAF) return;
|
||||
|
||||
auto internalNode = dynamic_cast<AABBTreeNodeInternal*>(node);
|
||||
CVF_ASSERT(internalNode);
|
||||
// Use an explicit stack instead of recursion. The tree can become very unbalanced (height
|
||||
// proportional to the leaf count rather than log2 of it), and recursing once per level would
|
||||
// overflow the call stack when the tree is destroyed. Deleting an internal node does not touch
|
||||
// its children, so the children pointers are read before the node is deleted and the order in
|
||||
// which the internal nodes are deleted does not matter.
|
||||
std::vector<AABBTreeNodeInternal*> pendingNodes;
|
||||
pendingNodes.push_back(static_cast<AABBTreeNodeInternal*>(node));
|
||||
|
||||
AABBTree::deleteInternalNodesBottomUp(internalNode->left());
|
||||
AABBTree::deleteInternalNodesBottomUp(internalNode->right());
|
||||
while (!pendingNodes.empty())
|
||||
{
|
||||
AABBTreeNodeInternal* internalNode = pendingNodes.back();
|
||||
pendingNodes.pop_back();
|
||||
|
||||
delete internalNode;
|
||||
AABBTreeNode* left = internalNode->left();
|
||||
AABBTreeNode* right = internalNode->right();
|
||||
|
||||
if (left && left->type() == AB_INTERNAL) pendingNodes.push_back(static_cast<AABBTreeNodeInternal*>(left));
|
||||
if (right && right->type() == AB_INTERNAL) pendingNodes.push_back(static_cast<AABBTreeNodeInternal*>(right));
|
||||
|
||||
delete internalNode;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user