Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<xtree>: Use scope guard for node copy failure #4749

Merged
merged 1 commit into from
Jul 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions stl/inc/xtree
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,20 @@ public:
using _Unchecked_const_iterator = _Tree_unchecked_const_iterator<_Tree_val>;
using const_iterator = _Tree_const_iterator<_Tree_val>;

template <class _AllocNode>
struct _NODISCARD _Erase_tree_and_orphan_guard {
_Tree_val* _Val_ptr;
_AllocNode& _Al;
_Nodeptr _New_root;

_Erase_tree_and_orphan_guard& operator=(const _Erase_tree_and_orphan_guard&) = delete;
~_Erase_tree_and_orphan_guard() noexcept {
if (_Val_ptr != nullptr) {
_Val_ptr->_Erase_tree_and_orphan(_Al, _New_root); // subtree copy failed, bail out
}
}
};

_Tree_val() noexcept : _Myhead(), _Mysize(0) {}

enum _Redbl { // colors for link to parent
Expand Down Expand Up @@ -1661,20 +1675,16 @@ protected:
_Nodeptr _Newroot = _Scary->_Myhead; // point at nil node

if (!_Rootnode->_Isnil) { // copy or move a node, then any subtrees
_Nodeptr _Pnode = _Copy_or_move<_Strat>(_Rootnode->_Myval);
_Pnode->_Parent = _Wherenode;
_Pnode->_Color = _Rootnode->_Color;
if (_Newroot->_Isnil) {
_Newroot = _Pnode; // memorize new root
}
_Newroot = _Copy_or_move<_Strat>(_Rootnode->_Myval); // memorize new root
_Newroot->_Parent = _Wherenode;
_Newroot->_Color = _Rootnode->_Color;

typename _Scary_val::template _Erase_tree_and_orphan_guard<_Alnode> _Guard{_Scary, _Getal(), _Newroot};

_Newroot->_Left = _Copy_nodes<_Strat>(_Rootnode->_Left, _Newroot);
_Newroot->_Right = _Copy_nodes<_Strat>(_Rootnode->_Right, _Newroot);

_TRY_BEGIN
_Pnode->_Left = _Copy_nodes<_Strat>(_Rootnode->_Left, _Pnode);
_Pnode->_Right = _Copy_nodes<_Strat>(_Rootnode->_Right, _Pnode);
_CATCH_ALL
_Scary->_Erase_tree_and_orphan(_Getal(), _Newroot); // subtree copy failed, bail out
_RERAISE;
_CATCH_END
_Guard._Val_ptr = nullptr;
}

return _Newroot; // return newly constructed tree
Expand Down