2014-10-17 3 views
0

Я знаю, что ошибка двойного освобождения или коррупции обычно является нарушением большого 3, но в этом случае я не могу найти, где происходит нарушение. У меня есть конструктор копирования, деструктор и оператор присваивания для всего, что касается указателей.double free или коррупция (out) C++

В моей .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, но это наименее я должен воспроизвести мою ошибку. Stack Trace

+1

Используйте Valgrind или отладчик, чтобы точно определить проблему. Как минимум, вы должны иметь возможность включить трассировку стека в свой вопрос. –

+0

@JohnZwinck есть совместимый с Windows, а также совместимый с C++ 11? У меня нет доступа к машине linux atm – SemicolonExpected

+0

Вы не включили конструктор BinaryNode. –

ответ

3

Рассмотрите ваш оператор назначения 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, имеющих свои left и right указатели, указывающие на то же самое. Когда вызываются деструкторы двух экземпляров, они освобождают указатели и вызывают двойное освобождение.

Что вам нужно сделать, это на самом деле сделать новую копию на значении на который указует left и right указателей, а не указателей или имеет какое-то подсчет ссылок указателя.

Также обратите внимание: Вы, если тесты не добавляют никакой ценности, как вы только назначая nullptr, если исходное значение является nullptr

+0

Как я могу это сделать? Должно ли это быть что-то вроде 'left = new BST :: BinaryNode (left-> item)' и что будет рекурсивно создавать новое «поддерево», идентичное первому или не будет работать? – SemicolonExpected

+1

Да, это правильно.Весь ваш конструктор копирования должен был бы рекурсивно называть себя для 'left' и' right' узлов, если они не 'nullptr'. К счастью, у вас уже есть тесты if, которые вам нужны :) –

+0

На самом деле вы хотите 'left = BST :: BinaryNode (node.left)', поэтому вы вызываете конструктор копирования. –

Смежные вопросы