Почему моя функция печати выдает эту ошибку для моей программы postfix?

Я пытаюсь написать программу для вычисления выражений постфикса, она включает в себя как драйвер, так и файл реализации. Эти два показаны ниже:

#include <cstdlib>
#include <iostream>
#include <string>
#include "Stack.h"
using namespace std;

void printStack(Stack<float>);

int main()
{
Stack<float> postFix;
float userIn, operand1, operand2;
// while the end of the postfix hasn't been reached
do
{
// prompt user for next number or modulus command
cout << "ENTER: ";
if (!postFix.isEmpty()) printStack(postFix);
string userInput;
cin >> userInput;

// If user input is q or Q then terminate program
if (userInput == "q" || userInput == "Q") return 0;
else
{
// read next token by parsing userInput
// if token is a number push it onto stack
if (userInput != "+" && userInput != "/" && userInput != "*" && userInput != "-")
{
userIn = atof(userInput.c_str());
postFix.push(userIn);
}
else if (!(postFix.size() < 2))
{
// if it's not a number then pop element from the stack and call it
// operand2
operand2 = postFix.lastElem();
postFix.pop();

// pop another element from the stack; call it operand1
operand1 = postFix.lastElem();
postFix.pop();

// Perform the operation: operand1 token operand2 and
// push the result of the operation onto the stack
if (userInput == "/")
postFix.push((operand1 / operand2));
else if (userInput == "*")
postFix.push((operand1 * operand2));
else if (userInput == "+")
postFix.push((operand1 + operand2));
else if (userInput == "-")
postFix.push((operand1 - operand2));
}
else if (postFix.size() < 2)
cout << "Stack is too small, request ignored\n";
} // end else

} while (!postFix.isEmpty()); // end while

// empty the stack
postFix.makeEmpty();

return 0;
}

// The problem is in the print function!

void printStack(Stack<float> postFix)
{
do
{
cout << postFix.lastElem() << " ";
postFix.pop();
} while (!postFix.isEmpty());
}

Мой файл реализации показан здесь:

#include <iostream>
using namespace std;

template <class DataType>
class Stack
{
public:
Stack() // constructor
{
capacity = 2;
//Stack(capacity);
elements = new DataType[capacity];
top = -1;
}

Stack(int s) // constructor with one parameter
{
capacity = s;
elements = new DataType[capacity];
top = -1;
}

~Stack()
{
delete [] elements;
}

bool isEmpty() const {return -1 == top;}

void pop() // pop function
{
//if (-1 == top) return; // failed
top--;
if (top > 2 && top < (capacity / 4))
{
capacity /= 2;
changeSize(capacity);
}
}

DataType & lastElem()
{
return elements[top];
}

int size() {return top;}

void push(float parameter) // push function
{
if (++top == capacity)
{
capacity *= 2;
changeSize(capacity);
}
elements[top] = parameter;
}

bool peek(DataType& parameter) const
{
if (-1 == top) return false; // failed
parameter = elements[top];
return true; // success
}

inline DataType & operator=(const Stack<DataType>& a)
{
if (this != &a)
{
delete [] elements;
elements = 0;
capacity = a.capacity;
if (capacity > 0)
elements = new DataType[capacity];
for (int i = 0; i < capacity; i++)
elements[i] = a.elements[i];
top = a.top;
}
return *this;
}

void changeSize(float newSize) // function for changing the array size if it's too small
{
DataType *newArray = new DataType[(int)newSize];
int limit = (newSize > capacity)? capacity : newSize;

for (int i = 0; i < limit; i++)
{
newArray[i] = elements[i];
}
delete [] elements;
elements = newArray;
capacity = newSize;
}

void makeEmpty() {top = -1;}

private:
DataType* elements;
int capacity;
int top; // track newest value
};

После компиляции этой программы с использованием g ++ я могу ввести до двух значений, пока не получу странную ошибку памяти, показанную ниже:

ENTER: 23
ENTER: 23 43
*** glibc detected *** ./calc: double free or corruption (fasttop): 0x0000000000c86010 ***
======= Backtrace: =========
/lib/libc.so.6(+0x78b06)[0x7fbd11e4ab06]
/lib/libc.so.6(cfree+0x73)[0x7fbd11e513d3]
./calc[0x401197]
./calc[0x400d9b]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7fbd11df0c4d]
./calc[0x400c09]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:06 788295                             /home/badr/Documents/My programs/COMSC-210/calc
00601000-00602000 r--p 00001000 08:06 788295                             /home/badr/Documents/My programs/COMSC-210/calc
00602000-00603000 rw-p 00002000 08:06 788295                             /home/badr/Documents/My programs/COMSC-210/calc
00c86000-00ca7000 rw-p 00000000 00:00 0                                  [heap]
7fbd0c000000-7fbd0c021000 rw-p 00000000 00:00 0
7fbd0c021000-7fbd10000000 ---p 00000000 00:00 0
7fbd11dd2000-7fbd11f4f000 r-xp 00000000 08:06 5813                       /lib/libc-2.11.1.so
7fbd11f4f000-7fbd1214e000 ---p 0017d000 08:06 5813                       /lib/libc-2.11.1.so
7fbd1214e000-7fbd12152000 r--p 0017c000 08:06 5813                       /lib/libc-2.11.1.so
7fbd12152000-7fbd12153000 rw-p 00180000 08:06 5813                       /lib/libc-2.11.1.so
7fbd12153000-7fbd12158000 rw-p 00000000 00:00 0
7fbd12158000-7fbd1216e000 r-xp 00000000 08:06 1268                       /lib/libgcc_s.so.1
7fbd1216e000-7fbd1236d000 ---p 00016000 08:06 1268                       /lib/libgcc_s.so.1
7fbd1236d000-7fbd1236e000 r--p 00015000 08:06 1268                       /lib/libgcc_s.so.1
7fbd1236e000-7fbd1236f000 rw-p 00016000 08:06 1268                       /lib/libgcc_s.so.1
7fbd1236f000-7fbd123f1000 r-xp 00000000 08:06 5814                       /lib/libm-2.11.1.so
7fbd123f1000-7fbd125f0000 ---p 00082000 08:06 5814                       /lib/libm-2.11.1.so
7fbd125f0000-7fbd125f1000 r--p 00081000 08:06 5814                       /lib/libm-2.11.1.so
7fbd125f1000-7fbd125f2000 rw-p 00082000 08:06 5814                       /lib/libm-2.11.1.so
7fbd125f2000-7fbd126e8000 r-xp 00000000 08:06 322753                     /usr/lib/libstdc++.so.6.0.13
7fbd126e8000-7fbd128e8000 ---p 000f6000 08:06 322753                     /usr/lib/libstdc++.so.6.0.13
7fbd128e8000-7fbd128ef000 r--p 000f6000 08:06 322753                     /usr/lib/libstdc++.so.6.0.13
7fbd128ef000-7fbd128f1000 rw-p 000fd000 08:06 322753                     /usr/lib/libstdc++.so.6.0.13
7fbd128f1000-7fbd12906000 rw-p 00000000 00:00 0
7fbd12906000-7fbd12926000 r-xp 00000000 08:06 5815                       /lib/ld-2.11.1.so
7fbd12afa000-7fbd12afe000 rw-p 00000000 00:00 0
7fbd12b21000-7fbd12b25000 rw-p 00000000 00:00 0
7fbd12b25000-7fbd12b26000 r--p 0001f000 08:06 5815                       /lib/ld-2.11.1.so
7fbd12b26000-7fbd12b27000 rw-p 00020000 08:06 5815                       /lib/ld-2.11.1.so
7fbd12b27000-7fbd12b28000 rw-p 00000000 00:00 0
7fff78cf3000-7fff78d08000 rw-p 00000000 00:00 0                          [stack]
7fff78dff000-7fff78e00000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
ENTER: 43 0 Aborted

После большой отладки я определил, что проблема должна быть в функции печати, расположенной в файле .cpp:

// The problem is in the print function!

void printStack(Stack<float> postFix)
{
do
{
cout << postFix.lastElem() << " ";
postFix.pop();
} while (!postFix.isEmpty());
}

Я просто не могу понять, почему это происходит или как это преодолеть.

2

Решение

void printStack(Stack<float> postFix) принимает параметр по значению, поэтому копия сделана. Использование созданного компилятором конструктора копирования. Который делает мелкую копию. Вам нужно будет реализовать свой собственный, который делает глубокую копию.

У вас уже есть оператор назначения копирования (operator =) и деструктор. Что правильно, но недостаточно. Эти 2 плюс конструктор копирования Stack(const Stack<DataType>& other) составляют правило трех. Если вам нужен один из них, вам нужны все. И обычно они нужны вам всем, когда вы управляете памятью в классе, которым вы являетесь.

Реализация похожа на operator =:

DataType(const Stack<DataType>& a)
{
elements = 0;
capacity = a.capacity;
if (capacity > 0)
elements = new DataType[capacity];
for (int i = 0; i < capacity; i++)
elements[i] = a.elements[i];
top = a.top;
}

Кроме того, на случай, если это не для образовательных целей, есть предварительно std::stack в шапке <stack> который вы можете использовать.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]