在C ++中使用递归方法时双重自由或损坏(fasttop)

时间:2014-03-04 21:28:21

标签: c++ recursion double-free

我实现了一个Stack类,并试图利用该类来解决Hanoi问题。这是我的代码:

template<class Datatype>
class Node
{
    public:
        Node()
        {
            next = NULL;
            prev = NULL;
        }
        Node* getNext()
        {
            return next;
        }
        Node* getPrev()
        {
            return prev;
        }
        Datatype* getData()
        {
            return &data;
        }
        void changeNext()
        {
            next = NULL;
        }
        void changeNext(Node& nextNode)
        {
            next = &nextNode;
        }
        void changePrev()
        {
            prev = NULL;
        }
        void changePrev(Node& prevNode)
        {
            prev = &prevNode;
        }
        Node* addNext(Node &);
        Node* addPrev(Node &);
        void nodeDel();
        void addData(Datatype &);
    private:
        Node* next;
        Node* prev;
        Datatype data;
};

template<class Datatype>
class Stack
{
    public:
        Stack() : head( NULL )
        {

        }
        virtual ~Stack()
        {
            Datatype temp;
            while (pop(temp));
            cout << "Stack released all spaces" << endl;
        }
    public:
        virtual int push(Datatype &);
        virtual int pop(Datatype &);
        virtual Datatype* peek();
    protected:
        Node<Datatype> *head;
};
template <class Datatype>
int Stack<Datatype>::push(Datatype &new_data)
{
    Node<Datatype> *pt_node = new Node<Datatype>;
    if (pt_node == NULL)
        return -1;

    pt_node -> addData(new_data);

    if (head == NULL)
        head = pt_node;
    else
    {
        pt_node -> addPrev(*head);
        head = pt_node;
    }

    //cout << *(head -> getData()) << endl;

    return 0;
}

template <class Datatype>
int Stack<Datatype>::pop(Datatype &pop_data)
{
    if (head == NULL)
        return 0;

    pop_data = *(head -> getData());

    if (head -> getNext() == NULL)
    {
        delete head;
        head = NULL;
    }
    else
    {
        Node<Datatype>* temp = head;
        head = head -> getNext();
        delete temp;
    }

    return 1;
}

以上声明Stack class并实施pop()push()功能。 现在,我宣布我的Hanoi课程并实现功能。

class Hanoi
{
    public:
        Hanoi(int num) : a_tower(), b_tower(), c_tower()
        {
            deep = num;
            int i;
            for (i = num; i != 0; i --)
                a_tower.push(i);
        }
    public:
        void workdone(int, Stack<int>&, Stack<int>&, Stack<int>&);
        void showret();
    public:
        Stack<int> a_tower;
        Stack<int> b_tower;
        Stack<int> c_tower;
        int deep;
};  

void Hanoi::workdone(int deep_num, Stack<int>& A, Stack<int>& B, Stack<int>& C)
{
    int temp;
    if (deep_num == 1)
    {
        A.pop(temp);
        C.push(temp);
    }       
    else
    {
        Hanoi::workdone(deep_num - 1, A, C, B);
        A.pop(temp);
        C.push(temp);
        Hanoi::workdone(deep_num - 1, B, A, C);
    }
}

void Hanoi::showret()
{
    int temp;
    while (c_tower.pop(temp) != 0)
        cout << temp << endl;
}

这是我的测试代码:

int main()
{
    Hanoi test(STACK_DEEP);
    test.workdone(STACK_DEEP, test.a_tower, test.b_tower, test.c_tower);
    test.showret();

    return 0;
}

输出结果为:

*** glibc detected *** ./3_4: double free or corruption (fasttop): 0x090c0038 ***

我认为这个问题在〜河内被召唤时发生,但我真的不知道为什么会发生这种情况。

在这里,我发布了可以获得此结果的整个代码: my_node.h

#include <iostream>

using namespace std;

template<class Datatype>
class Node
{
    public:
        Node()
        {
            next = NULL;
            prev = NULL;
        }
        Node* getNext()
        {
            return next;
        }
        Node* getPrev()
        {
            return prev;
        }
        Datatype* getData()
        {
            return &data;
        }
        void changeNext()
        {
            next = NULL;
        }
        void changeNext(Node& nextNode)
        {
            next = &nextNode;
        }
        void changePrev()
        {
            prev = NULL;
        }
        void changePrev(Node& prevNode)
        {
            prev = &prevNode;
        }
        Node* addNext(Node &);
        Node* addPrev(Node &);
        void nodeDel();
        void addData(Datatype &);
    private:
        Node* next;
        Node* prev;
        Datatype data;
};

template<class Datatype>
class Stack
{
    public:
        Stack() : head( NULL )
        {

        }
        virtual ~Stack()
        {
            Datatype temp;
            while (pop(temp));
            cout << "Stack released all spaces" << endl;
        }
    public:
        virtual int push(Datatype &);
        virtual int pop(Datatype &);
        virtual Datatype* peek();
    protected:
        Node<Datatype> *head;
};

template <class Datatype>
Node<Datatype>* Node<Datatype>::addNext(Node<Datatype>& exi_node)
{
    if (exi_node.getNext() == NULL)
    {
        changePrev(exi_node);
        exi_node.changeNext(*this);
    }
    else
    {
        Node* next = exi_node.getNext();
        changePrev(exi_node);
        changeNext(*next);
        exi_node.changeNext(*this);
        next -> changePrev(*this);
    }
    return &exi_node;
}

template <class Datatype>
Node<Datatype>* Node<Datatype>::addPrev(Node<Datatype>& exi_node)
{
    if (exi_node.getPrev() == NULL)
    {
        changeNext(exi_node);
        exi_node.changePrev(*this);
    }
    else
    {
        Node* prev = exi_node.getPrev();
        changePrev(*prev);
        changeNext(exi_node);
        exi_node.changePrev(*this);
        prev -> changeNext(*this);
    }
    return &exi_node;
}

template<class Datatype>
void Node<Datatype>::nodeDel()
{
    if (prev == NULL && next == NULL)
        ;
    else if (prev == NULL)
    {
        Node* next = getNext();
        next -> changePrev();
    }
    else if (next == NULL)
    {
        Node* prev = getPrev();
        prev -> changeNext();
    }
    else
    {
        Node* next = getNext();
        Node* prev = getPrev();
        next -> changePrev(*prev);
        prev -> changeNext(*next);  
    }
    delete this;
    return;
}

template <class Datatype>
void Node<Datatype>::addData(Datatype &new_data)
{
    data = new_data;
}

template <class Datatype>
int Stack<Datatype>::push(Datatype &new_data)
{
    Node<Datatype> *pt_node = new Node<Datatype>;
    if (pt_node == NULL)
        return -1;

    pt_node -> addData(new_data);

    if (head == NULL)
        head = pt_node;
    else
    {
        pt_node -> addPrev(*head);
        head = pt_node;
    }

    //cout << *(head -> getData()) << endl;

    return 0;
}

template <class Datatype>
int Stack<Datatype>::pop(Datatype &pop_data)
{
    if (head == NULL)
        return 0;

    pop_data = *(head -> getData());

    if (head -> getNext() == NULL)
    {
        delete head;
        head = NULL;
    }
    else
    {
        Node<Datatype>* temp = head;
        head = head -> getNext();
        delete temp;
    }

    return 1;
}

template <class Datatype>
Datatype* Stack<Datatype>::peek()
{
    if (head == NULL)
        return NULL;
    return (this->head)->getData();
}

3_4.h

#include <iostream>
#include "my_node.h"

using namespace std;

class Hanoi
{
    public:
        Hanoi(int num) : a_tower(), b_tower(), c_tower()
        {
            deep = num;
            int i;
            for (i = num; i != 0; i --)
                a_tower.push(i);
        }
    public:
        void workdone(int, Stack<int>&, Stack<int>&, Stack<int>&);
        void showret();
    public:
        Stack<int> a_tower;
        Stack<int> b_tower;
        Stack<int> c_tower;
        int deep;
};  

void Hanoi::workdone(int deep_num, Stack<int>& A, Stack<int>& B, Stack<int>& C)
{
    int temp;
    if (deep_num == 1)
    {
        A.pop(temp);
        C.push(temp);
    }       
    else
    {
        Hanoi::workdone(deep_num - 1, A, C, B);
        A.pop(temp);
        C.push(temp);
        Hanoi::workdone(deep_num - 1, B, A, C);
    }
}

void Hanoi::showret()
{
    int temp;
    while (c_tower.pop(temp) != 0)
        cout << temp << endl;
}

3_4.cpp

#include <iostream>
#include "3_4.h"

using namespace std;

#define STACK_DEEP 4

int main()
{
    Hanoi test(STACK_DEEP);
    test.workdone(STACK_DEEP, test.a_tower, test.b_tower, test.c_tower);
    test.showret();

    return 0;
}

我使用的命令:

g++ -Wall 3_4.cpp -o 3_4

1 个答案:

答案 0 :(得分:3)

代码比它需要的更复杂(并且令人困惑),但错误归结为Node :: addPrev的错误实现

最小修复是将此函数的实现更改为:

    template <class Datatype>
    Node<Datatype>* Node<Datatype>::addPrev(Node<Datatype>& exi_node)
    {
        exi_node.prev = this;
        this->next = &exi_node;
        return &exi_node;
    }

正确的修复将涉及将Stack和Node类更改为更简单的实现 - 正如之前的评论者提到的那样,它不需要是双链表。