【问题标题】:Memory leak in C++ (Valgrind)C++ 中的内存泄漏 (Valgrind)
【发布时间】:2021-11-28 23:24:21
【问题描述】:

我以最少的方式实现堆栈。在这个程序中,我从 valgrind 得到一个错误。 push() 和 main() 函数有问题。当我添加删除 st;对于 push() 函数,我得到更多错误。我通过 valgrind ./a.out 检查它。抱歉,代码太长了。我还为堆栈编写了其余的函数。但是它们没有错误,我把那些留在代码中可能有错误的地方。

#include <cstring>
#include <iostream>

struct Stack {
  int data;
  int min;
  Stack* next;
};

void Push(Stack** top, int n) {
  Stack* st = new Stack();
  st->data = n;
  if (*top == NULL) {
    *top = st;
    (**top).min = n;
  } else {
    st->min = ((n <= (**top).min) ? n : (**top).min);
    st->next = *top;
    *top = st;
  }
  std::cout << "ok" << std::endl;
}

void Pop(Stack** top) {
  if (*top != NULL) {
    std::cout << (**top).data << std::endl;
    *top = (*top)->next;
  } else {
    std::cout << "error" << std::endl;
  }
}

int main() {
  Stack* top = nullptr;
  int m;
  std::cin >> m;
  std::string str;
  for (int i = 0; i < m; ++i) {
    std::cin >> str;
    if (str == "push") {
      int value;
      std::cin >> value;
      Push(&top, value);
    }
    if (str == "pop") {
      Pop(&top);
    }
  }
  delete top;
}

【问题讨论】:

  • 为什么PushPop 不是Stack 的成员函数?为什么要创建一个Stack 类,其中一半的函数与类外的堆栈相关(封装不好)?此外,避免内存泄漏的方法是不编写引入它们的代码。 std::stack&lt;int&gt; 是一个堆栈类,它接受整数并且没有内存泄漏。
  • 我是 C++ 编程新手。我曾经用 Python 编写。请不要严格判断。是的,这可能是一个糟糕的封装,但我被要求这样写。我被要求自己实现所有功能。
  • Stacknext 成员变量在*top == NULL 时未初始化。在 C++ 中初始化对象的新实例的惯用方式是定义一个构造函数,这样实例化和初始化是一起完成的。
  • 那你基本上是在学习C,而不是C++。要求退款。在这个 C++ 时代,代码不应该像你被要求写的那样。
  • Push 中有一个new,所以Pop 中应该有一个delete

标签: c++ stack valgrind


【解决方案1】:

当您只是 delete top 时,您会破坏它(在您的情况下它什么都不是,但如果有兴趣,您可以分散自己的注意力来阅读有关 destructors 的内容)并释放为 top 分配的动态内存。但是,您实际上还想要delete top-&gt;nexttop-&gt;next-&gt;next(如果存在)等。修补程序:

while (top) { // same as "while (top != nullptr) {"
    Stack* next = top->next; // we can't use `top` after we `delete` it, save `next` beforehand
    delete top;
    top = next;
}

现在,关于更一般的事情。该课程教你一些非常古老的 C++(几乎只是普通的 C;尽管这里的 C 也很糟糕)。至少,您的整个Push() 可以替换为(感谢lvalue references (Type&amp;)、std::minaggregate initialization):

void push(Stack*& top, int n) {
    top = new Stack{n, std::min(n, top ? top->min : n), top};
    std::cout << "ok\n";
}

我是 C++ 编程新手。我以前用 Python 写代码

干得好。可悲的是,这样的教学表明 C++ 太古老了,太可怕了。

编辑

这是 Push 中的新内容,因此 Pop 中应该很可能有删除

没错(感谢@molbdnilo)。你应该deletepopped 元素而不是仅仅泄露它们。

【讨论】:

    猜你喜欢
    • 2020-03-31
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    • 2013-06-24
    • 2019-07-02
    • 1970-01-01
    相关资源
    最近更新 更多