-1

#pragma once

#include <iostream>
using namespace std;

/**
 * A template Stack class
 */
template <typename T> 
class Stack {
private:
    // data array
    T* array;
    // Number of elements in use
    int count;
    // allocation size of the array, in number of elements
    int allocation_size;

    /**
     * @brief Resize the data array to double its allocation size
     * Make sure to release memory allocation correctly.
     */
    void resizeArray();
public:
    // Constructor
    Stack(int capacity = 4);

    // Destructor
    ~Stack();
    
    // Copy constructor
    Stack(const Stack<T>& stk);

    // Assignment operator
    Stack<T>& operator = (const Stack<T>& stk);

    /**
     * @brief Push a value to the stack.
     * The array will be resized if it reaches its capcity
     * @param val Value to be pushed onto the stack
     */
    void push(const T& val);

    /**
     * @brief If not empty, removes and gives back the top element;
     * @param val variable to receive the popped element (by ref)
     */
    void pop(T& val);

    /**
     * @brief Returns a reference to the top most element of the stack
     * @return reference to top element of the stack
     */
    T& top();

    /**
     * @brief Check if the stack is empty
     * @return true if stack is empty
     */
    bool isEmpty();

/**
     * @brief Returns the number of elements in the stack
     * @return int the number of elements in the stack
     */
    int size();

    /**
     * @brief Display the content of the stack
     */
    void displayAll();

    /**
     * @brief Clear the stack to make it empty
     */
    void clearAll();
};

template <typename T>
Stack<T>::Stack(int capacity) {
    // TODO: Add your code here
    array = new T[capacity];
    allocation_size = capacity;
    count = 0;
}

template <typename T>
Stack<T>::~Stack() {
    // TODO: Add your code here
    delete array;
}

// @brief Copy constructor
template <typename T>
Stack<T>::Stack(const Stack<T>& stk) {
   // TODO: Add you code here
   allocation_size = stk.allocation_size;
   array = new T[allocation_size];
   count = stk.count;
   for (int i = 0; i < count; i++){
       array[i] = stk.array[i];
   }
}

template <typename T>
Stack<T>& Stack<T>::operator = (const Stack<T>& stk) {
  // TODO: Add you code here
  delete array;
  allocation_size = stk.allocation_size;
  array = new T[allocation_size];
  count = stk.count;
  for (int i = 0; i < count; i++){
      array[i] = stk.array[i];
  }

  return *this;
  
}

// TODO: Add implementation of remaining Stack functions.
// For a template class, the implementation should be included in the header file.

//@brief Resize the data array to double its allocation size
template <typename T>
void Stack<T>::resizeArray() {
    T* new_array = new T[allocation_size * 2];
    for (int i = 0; i < count; i++) {
        new_array[i] = array[i];
    }
    allocation_size *= 2;
    delete[] array;
    array = new_array;
}

// @brief Push a value to the stack.
template <typename T>
void Stack<T>::push(const T& val) {
   // TODO: Add your code here
    array[count] = val;
    count++;
}

// @brief If not empty, removes and gives back the top element;
template <typename T>
void Stack<T>::pop(T& val) {
    // TODO: Add your code here
    --count;
    val = array[count];
}

// @brief Returns a reference to the top most element of the stack
template <typename T>
T& Stack<T>::top() {
    // TODO: Add your code here
    return array[count];
}

// @brief Check if the stack is empty
template <typename T>
bool Stack<T>::isEmpty() {
    // TODO: Add your code here
    return count < 0;
}

// @brief Returns the number of elements in the stack
template <typename T>
int Stack<T>::size() {
    // TODO: Add your code here
    return count;
}

// @brief Display the content of the stack
template <typename T>
void Stack<T>::displayAll() {
    if (count == 0) {
        cout << "Stack is empty" << endl;
    } else {
        for (int i = 0; i < count; i++) {
            cout << array[i] << " ";
        }
        cout << endl;
    }
}

The above is the code for my .h file.

/**
 * This file tests the implementation of Stack data structure
 * 
 */
#include "stack.h"
#include <iostream>
#include "assert.h"

using namespace std;

int main(int argc, char* argv[]) {
    cout << "Create a new stack" << endl;
    Stack <int> stack;
    assert(stack.size() == 0);
    cout << "push 1,  stack = " << endl;
    stack.push(1);
    stack.displayAll();

    // Test push function
    for(int i = 0; i < 10; i++) {
        stack.push(i);
        cout << "push " << i << ", stack = ";
        stack.displayAll();
    }


    // Test pop function
    for (int i = 0; i < 5; i++) {
        int x;
        stack.pop(x);
        cout << "pop top val = " << x << ", stack = ";
        stack.displayAll();
    }


    // Test copy constructor 
    cout << "Test copy constructor, s2 as a copy of stack" << endl;
    Stack<int> s2(stack);
    cout << "s2 size = " << s2.size() << endl;
    cout << "s2 = ";
    s2.displayAll();
    assert(s2.size() == stack.size());
    assert(s2.top() == stack.top());

    
}

The above is the code for my .cpp file.

So the issue I'm having is during the "Test copy instructor" part of the .cpp file. After running it I end up with:

Create a new stack
push 1,  stack = 
1 
push 0, stack = 1 0 
push 1, stack = 1 0 1 
push 2, stack = 1 0 1 2 
push 3, stack = 1 0 1 2 3 
push 4, stack = 1 0 1 2 3 4 
push 5, stack = 1 0 1 2 3 4 5 
push 6, stack = 1 0 1 2 3 4 5 6 
push 7, stack = 1 0 1 2 3 4 5 6 7 
push 8, stack = 1 0 1 2 3 4 5 6 7 8 
push 9, stack = 1 0 1 2 3 4 5 6 7 8 9 
pop top val = 9, stack = 1 0 1 2 3 4 5 6 7 8 
pop top val = 8, stack = 1 0 1 2 3 4 5 6 7 
pop top val = 7, stack = 1 0 1 2 3 4 5 6 
pop top val = 6, stack = 1 0 1 2 3 4 5 
pop top val = 5, stack = 1 0 1 2 3 4 
Test copy constructor, s2 as a copy of stack
s2 size = 6
s2 = 1 0 1 2 1 0 
Assertion failed: (s2.top() == stack.top()), function main, file test1.cpp, line 43.

So the code isn't passing the assertion test which I can see that the s2 array ends up with the numbers: 1 0 1 2 1 0. When it should be 1 0 1 2 3 4. The thing is when I set the debugger to the "Test copy constructor" with a break right before and a break right after. The correct numbers get printed:

Create a new stack
push 1,  stack = 
1 
push 0, stack = 1 0 
push 1, stack = 1 0 1 
push 2, stack = 1 0 1 2 
push 3, stack = 1 0 1 2 3 
push 4, stack = 1 0 1 2 3 4 
push 5, stack = 1 0 1 2 3 4 5 
push 6, stack = 1 0 1 2 3 4 5 6 
push 7, stack = 1 0 1 2 3 4 5 6 7 
push 8, stack = 1 0 1 2 3 4 5 6 7 8 
push 9, stack = 1 0 1 2 3 4 5 6 7 8 9 
pop top val = 9, stack = 1 0 1 2 3 4 5 6 7 8 
pop top val = 8, stack = 1 0 1 2 3 4 5 6 7 
pop top val = 7, stack = 1 0 1 2 3 4 5 6 
pop top val = 6, stack = 1 0 1 2 3 4 5 
pop top val = 5, stack = 1 0 1 2 3 4 
Test copy constructor, s2 as a copy of stack
s2 size = 6
s2 = 1 0 1 2 3 4 
Assertion failed: (s2.top() == stack.top()), function main, file test1.cpp, line 43.
Signal: SIGABRT (hit program assert)
Terminated due to signal 6

However, it still says that it fails the assertion. I'm not sure where in my code the error lies, if anyone sees anything obvious or could point me in the right direction I'd appreciate it!

  • 1
    `array[count]` is out of bounds. `array[count - 1]` is the last valid item. – Miles Budnek Oct 14 '22 at 23:58
  • Don’t forget to check source and destination of assignment are same in operator= – Özgür Murat Sağdıçoğlu Oct 15 '22 at 00:00
  • Handy tool: https://godbolt.org/z/1cK9scK4b Note the -fsanitize argument in the compiler options. This turns on a bunch of extra tools that make many types of errors trivial to track down. I n this case I added in undefined behaviour and bass addressing checks. It immediately calls out what Miles spotted. Fix that, run it again and you'll probably find more. – user4581301 Oct 15 '22 at 00:01
  • That said, I'm pretty sure `count` is innocent. What you need is s test to make sure `count` does not exceed `allocation_size`. Probably want to resize if it does. – user4581301 Oct 15 '22 at 00:07

1 Answers1

-1

The array is out of bounds in the top() function.

The problem is with the top() function. Use "count-1" in top()