当我调用解构器时,这会导致内存泄漏吗?

时间:2015-11-10 23:32:01

标签: c++

我有一个我必须为我的Uni类做的数据结构项目,它实现了一个带有链表的堆栈;简单的东西。我们在代码方面得到了一些帮助,向我们展示了实现这种结构的正确方法。

Stack class:

class Stack
{
public:
    Stack(void)
    {
        top = NULL;     // Initialises defualt top node pointer.
    }

    ~Stack(void)
    {
        while (NodePop() != NULL){}
    }

    void Push(int value)    // Pushes a new node onto the stack.
    {
        Node* temp = new Node(value, top);  // Creates a temporary node with a value and makes it 
                                            // point to the top node as the next node in the stack.

        top = temp;                         // Temporary node becomes the top node in the stack.
    }

    Node* NodePop(void)
    {
        /* Remove top node from the stack */
        Node* temp = top;                       // Creates a temporary node to return, sets it to top node.
        if (top != NULL) top = top->getNext();  // Points the stacks top node to the next node in the list.
        return temp;                            // Returns a pointer to the popped node still in the heap.
    }

    int Pop(void)       // Pops the top node off of the stack. Returns the nodes value.
    {
        Node* temp = NodePop();     
        int valueReturn = 0;

        /* Sets the return value */
        if (temp != NULL)
        {
            valueReturn = temp->getVal();   // Set return value to the nodes value if there is a node left.
        }
        else
        {
            throw "Stack Empty";            // Throws exception if temp is NULL and stack is empty. 
        }

        delete temp;            // Deletes the node entirely from the heap.

        return valueReturn;
    }

private:
    Node* top;

};

节点类:

class Node
{
public:
    Node(int value, Node* nextptr = NULL, Node* prevptr = NULL, int currentpriority = 0)
    {
        /* Set initial variables for the node at creation */
        this->value = value;
        this->next = nextptr;
        this->prev = prevptr;
        this->priority = currentpriority;
    }

    // bunch of getters and setters...

private:
    Node* next;     // Pointer to the next node.
    Node* prev;     // Pointer to the previous node.
    int priority;   // Stores the node priority as a number 0-9.
    int value;      // Stores the node value for printing.

};

我们不能改变任何类结构(我的烦恼,NodePop()应该是私有的,但是w / e)。

所以这里NodePop()基本上从列表中删除了顶级节点,但是没有删除它;它从链表中删除对它的所有引用,但它从不从堆中删除它,它只从Pop()中的堆中删除。一切都很好(除了能够公开调用NodePop(),但同样,我不允许将其设为私有)。但是当我调用析构函数时,必须使用NodePop(),而不是Pop()。

这是否意味着当NodePop()从析构函数运行时,节点永远不会从堆中删除?

如果是这样,我将如何删除它们,因为如果我在while,do-while或if语句中有它,那么它将会运行nodePop()所以总会有一个节点被取消删除吗

2 个答案:

答案 0 :(得分:3)

查看有问题的代码

~Stack(void)
{
    while (NodePop() != NULL){}
}

Node* NodePop(void)
{
    /* Remove top node from the stack */
    Node* temp = top;                       // Creates a temporary node to return, sets it to top node.
    if (top != NULL) top = top->getNext();  // Points the stacks top node to the next node in the list.
    return temp;                            // Returns a pointer to the popped node still in the heap.
}

你的析构函数调用NodePop()直到该函数返回NULL。让我们看看NodePop()的作用。代码中的注释声称它Creates a temporary node to return这不是真的。它创建一个指向Node(Node *)的指针,并将该指针设置为指向top所在的相同位置。如果top不为空,则会将top设置为指向顶部的下一个节点。返回temp,其中是指向最初节点的指针。

在任何时候你都没有释放与任何节点相关的内存,所以是的是内存泄漏。

您可以通过删除在析构函数中遇到的非NULL的每个Node *来修复泄漏。

答案 1 :(得分:0)

实际上,节点不会被删除,而且这段代码会泄漏。您可以使用Valgrind等工具验证这一点。

我会将while更改为while (Node *N = NodePop()) delete N;

仅供参考,这段代码绝对不是惯用的C ++ 11。它的写作基本上写得不好C,我希望能找到更多的错误。你的老师应该在手腕上打一巴掌,就像这样呈现C ++ 11: - )