#c #stack #valgrind
Вопрос:
Я реализую стек с минимумом. В этой программе я получаю сообщение об ошибке от valgrind. Что-то не так с функциями push() и main (). Когда я добавляю delete 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(amp;top, value);
}
if (str == "pop") {
Pop(amp;top);
}
}
delete top;
}
Комментарии:
1. Почему
Push
функции-члены и неPop
являются функциямиStack
? Почему вы создалиStack
класс, в котором половина функций, связанных со стеками, находится за пределами класса (плохая инкапсуляция)? Кроме того, способ избежать утечек памяти состоит в том, чтобы не писать код, который их создает.std::stack<int>
это класс стека, который принимает целые числа и не имеет утечек памяти.2. Я новичок в программировании на C . Раньше я писал на Python. Пожалуйста, не судите строго. Да, это может быть плохая инкапсуляция, но меня попросили написать это таким образом. Меня попросили реализовать все функции самостоятельно.
3. Переменная
next
— членStack
неинициализирована, когда*top == NULL
. Идиоматический способ инициализации нового экземпляра объекта в C заключается в определении конструктора, таким образом, создание экземпляра и инициализация выполняются вместе.4. Тогда вы в основном учитесь
C
, а неC
. Попросите вернуть деньги. В наши дни и в эпоху C код не должен выглядеть так, как вам было поручено написать.5. Есть
new
входPush
, так что, скорее всего, он должен бытьdelete
Pop
.
Ответ №1:
Когда вы просто delete top
уничтожаете его (в вашем случае это ничего , но вы можете отвлечься на чтение о деструкторах, если вам интересно) и освободить выделенную динамическую память top
. Однако на самом деле вы тоже хотите delete
top->next
top->next->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 ( Typeamp;
) std::min
и агрегированной инициализации) на:
void push(Stack*amp; top, int n) {
top = new Stack{n, std::min(n, top ? top->min : n), top};
std::cout << "okn";
}
Я новичок в программировании на C . Раньше я писал на Python
Хорошая работа. К сожалению, такое обучение показывает, что C — это что-то слишком старое и ужасающее.
Редактировать
вот новое в Push, поэтому, скорее всего, в Pop должно быть удаление
Правильно (благодаря @molbdnilo). Вы должны delete
pop
удалять элементы, а не просто пропускать их.