【问题标题】:double free or corruption (out) C++双重释放或损坏(出)C++
【发布时间】:2014-10-17 02:44:19
【问题描述】:

我知道双重释放或损坏错误通常是违反大 3,但在这种情况下,我找不到违规发生的位置。对于处理指针的任何事情,我都有一个复制构造函数、析构函数和赋值运算符。

在我的 .h 中,这是我的类实现:

class BST
{
public:
    struct SequenceMap{
        std::string astring;
        std::vector<std::string> sequences;

        //void setValue(std::string theString, std::string anotherString);
        SequenceMap& operator=(const SequenceMap map);

        void setValue(std::string theString, std::string anotherString);

        SequenceMap(); //constructor no copy since no pointers
        ~SequenceMap();
    };
    struct BinaryNode{
        SequenceMap item;
        BinaryNode *left;
        BinaryNode *right;
        BinaryNode(SequenceMap i); //constructor

        inline bool operator> (std::string t);
        inline bool operator< (std::string t);

        BinaryNode& operator=(const BinaryNode node) ;
        ~BinaryNode();
        BinaryNode(const BinaryNode &otherNode);
    };
    BinaryNode *root;
    int insert(SequenceMap &x, BinaryNode *&t, bool &ifdup);

    BST();
    ~BST();
    void BSTClear(BST::BinaryNode *t);
    BST(const BST &otherTree);

    BST& operator=(const BST tree);
};

我在 .cpp 中实现了构造函数、析构函数和赋值运算符:

BST::SequenceMap& BST::SequenceMap::operator=(const BST::SequenceMap map) 
{
    astring = map.astring;
    sequences = map.sequences;
    return *this;
}

inline bool BST::BinaryNode::operator<(std::string t){//does compare}
inline bool BST::BinaryNode::operator>(std::string t){//does compare}

BST::BinaryNode& BST::BinaryNode::operator=(const BST::BinaryNode node) 
{
    item = node.item;
    if(node.left != nullptr)
        left = new BST::BinaryNode(node.left->item);
    else
        left = nullptr;
    if(node.right != nullptr)
        right = new BST::BinaryNode(node.right->item);
    else
        right = nullptr;

    return *this;
}
BST& BST::operator=(const BST tree){root = new BinaryNode(tree.root);}

BST::BinaryNode::BinaryNode(const BST::BinaryNode &otherNode){
    item = otherNode.item;  
    if(otherNode.left != nullptr)
        left = new BST::BinaryNode(otherNode.left->item);
    else
        left = nullptr;
    if(otherNode.right != nullptr)
        right = new BST::BinaryNode(otherNode.right->item);
    else
        right = nullptr;
}

BST::BinaryNode::BinaryNode(SequenceMap i){ item = i; left = nullptr; right = nullptr; }
BST::BinaryNode::~BinaryNode(){ delete &item; left = nullptr; right = nullptr; }

BST::BST(){root = nullptr;}
BST::BST(const BST &otherTree){root = new BinaryNode(otherTree.root->item);}
BST::~BST(){BSTClear(root);}

BST::SequenceMap::SequenceMap(){astring = "";}
BST::SequenceMap::~SequenceMap(){ delete &astring; delete &sequences;}

void BST::BSTClear(BST::BinaryNode*t){
    if(t->left != nullptr)
        BSTClear(t->left);
    if(t->right != nullptr)
        BSTClear(t->right);      
    delete t;
}

我使用cout 来测试错误发生的位置,并且当我在我的 main.cpp 中的指示行中执行此操作时发生错误:

while(getline(sequences,sequence) && getline(enzymes,enzyme))
{
    BST::SequenceMap map = BST::SequenceMap;
    map->setValue(sequence, enzyme);

    sequenceTree->insert(map, sequenceTree->root, dup); //ON THIS LINE
}

在我的 .cpp 中的插入函数中:

int BST::insert(BST::SequenceMap &x, BST::BinaryNode *&t, bool &ifdup )
{
    if(t == nullptr)
    {
        //std::cout<<"2"<<std::endl;            
        t = new BST::BinaryNode(x); //ON THIS LINE  
        //std::cout<<"1"<<std::endl;
    }
    //do more things
 }

我不确定这是否被视为 MSCV,但我至少需要重现我的错误。

【问题讨论】:

  • 使用 valgrind 或调试器来查明问题。您至少应该能够在问题中包含堆栈跟踪。
  • @JohnZwinck 是否有一个兼容 Windows 和 c++11 的?我无权访问 linux 机器 atm
  • 你没有包含 BinaryNode 构造函数。
  • 啊,我查看问题时你还没有添加它们。
  • BinaryNode 的析构函数中有delete &amp;item;。值&amp;item 不是分配的指针,因此您应该删除删除语句。但是,您应该删除 leftright,因为它们被分配了指针。

标签: c++ class memory constructor runtime-error


【解决方案1】:

考虑您的BinaryNode 赋值运算符。

BST::BinaryNode& BST::BinaryNode::operator=(const BST::BinaryNode node) 
{
    item = node.item;
    if(node.left != nullptr)
        left = node.left;
    else
        left = nullptr;
    if(node.right != nullptr)
        right = node.right;
    else
        right = nullptr;

    return *this;
}

你仍然会得到BinaryNode 的两个实例,它们的leftright 指针指向同一个东西。当调用两个实例的析构函数时,它们都会释放指针并导致双重释放。

您需要做的是实际制作一个新副本 values 指向的 leftright 指针,而不是 指针,或者某种引用计数指针。

另请注意:如果原始值为 nullptr,则您的 if 测试不会添加任何值,因为您只是分配 nullptr

【讨论】:

  • 我如何深拷贝这个?是否必须是 left = new BST::BinaryNode(left-&gt;item) 之类的东西,并且会递归地创建一个与第一个相同的新“子树”,还是不起作用?
  • 是的,没错。您的所有复制构造函数需要做的就是为leftright 节点递归调用自身,如果它们不是nullptr。幸运的是,您已经有了所需的 if 测试 :)
  • 其实你想要left = BST::BinaryNode(node.left),所以你调用了复制构造函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多