【问题标题】:Segmentation fault after calling reset on unique_ptr在 unique_ptr 上调用 reset 后出现分段错误
【发布时间】:2019-10-20 11:19:58
【问题描述】:

在 unique_ptr 上调用 reset 时遇到分段错误:

Node* tree::left_rotate(Node* node) {
    Node* temp = node->right.get();
    node->right.reset(temp->left.get());
    temp->left.reset(node); // **Here is segmentation fault happens**
    if(node->right.get()) {
        node->right->parent = node;
    }
    temp->parent = node->parent;
    if(node->parent) {
        if(node == node->parent->left.get()) {
            node->parent->left.reset(temp);
            node->parent = node->parent->left.get();
        } else if(node == node->parent->right.get()) {
            node->parent->right.reset(temp);
            node->parent = node->parent->right.get();
        }
    }
    return temp;
}

节点结构如下:

class Node {
    public:
        int data;
        Node* parent;
        std::unique_ptr<Node> left;
        std::unique_ptr<Node> right;
    public:
        Node() : data(0) {          
        }
        explicit Node(int d) : data(d),
                               parent(nullptr),
                               left(nullptr),
                               right(nullptr) {}        
};

gdb 报告:

线程 1 收到信号 SIGSEGV,分段错误。 0x00404ae5 在 std::unique_ptr >::~unique_ptr ( 这=0xfeeefefa,__in_chrg=) 在 C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/ unique_ptr.h:273 第273章

来自一个堆栈帧上方的报告:

#2  0x004047e8 in std::default_delete<Node>::operator() (this=0xfe1de4,
    __ptr=0xfeeefeee)
    at C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/unique_ptr.h:81
81              delete __ptr;

所以这里似乎是双重删除。如何解决这个问题?也许值得将临时指针用作 shared_ptr

【问题讨论】:

    标签: c++11 pointers segmentation-fault smart-pointers unique-ptr


    【解决方案1】:
    Node* temp = node->right.get();
    

    temp 是指向节点右节点的原始指针

    node->right.reset(temp->left.get());
    

    节点的右节点被重置为临时节点的左节点,因此原始节点的右节点(临时指向的节点)被删除。这意味着临时原始指针现在指向已删除的节点。

    temp->left.reset(node); // **Here is segmentation fault happens**
    

    当 temp 被删除时,解除对它的引用以获得它的左节点会导致不好的事情。

    快速思考,也许首先使用 release() 而不是 get() 来接管节点正确节点的所有权?

    【讨论】:

    • 似乎没有办法仅使用 unique_ptr 来实现正确的旋转。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2018-03-17
    • 2017-08-05
    相关资源
    最近更新 更多