0

Upon running this test file, I'm getting this output:

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

int main() 
{
    string Text;
    Stack S1;

    S1.push("Mary");
    S1.push("Apple");
    S1.push("Tom");
    S1.peek(Text);
    cout << "Results from peek: " << Text << endl;

    S1.view();
    cout << "Hello";
    
    Stack S2(S1);
}
Results from peek: Tom
TOP -> Tom -> Apple -> Mary -> BOTTOM
Segmentation fault

After some probing around, I believe the cause of this error to be in the destructor(?). Running GDB, it outputs this:

Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x55fa1e0ff3c3c990) at malloc.c:3102
3102    malloc.c: No such file or directory.

That means very little to me, could anyone make a little more sense of it? Thank you.

Edit: Using Valgrind, it outputs a very long line of code, which also doesn't make sense, but does confirm that the destructor is what is making the program unhappy. The first two errors are shown below.

==1236== Conditional jump or move depends on uninitialised value(s)
==1236==    at 0x10983D: Stack::~Stack() (in my_folder)
==1236==    by 0x1094D1: main (in my_folder)
==1236==
==1236== Use of uninitialised value of size 8
==1236==    at 0x109846: Stack::~Stack() (in my_folder)
==1236==    by 0x1094D1: main (in my_folder)
==1236==

My class is defined as follows:

typedef std::string SElement;

class Stack {
        public:
            Stack();
            Stack( Stack & );
            ~Stack();
            void push ( const SElement );
            void pop( SElement & );
            void peek( SElement & );
            void view();
        private:
            struct SNode;
            typedef SNode * SNodePtr;
            struct SNode {
                SElement element;
                SNodePtr next;
            };
            SNodePtr top;
};

Just in case, here's the other functions used:

void Stack::pop ( SElement &Text)
{
    if(top == nullptr) {
        cout << "The stack is empty. No StackElement has been removed." << endl;
    }
    else {
        SNodePtr SecondInLine = top->next;
        Text = top->element;
        delete top;
        top = SecondInLine;
    }
}
void Stack::push( const SElement Text)
{
    SNodePtr NewNode = new SNode;
    
    NewNode->next = top;
    NewNode->element = Text;
    top = NewNode;
}

Edit: added Default Constructor and Destructor.

Stack::Stack()
{
    top = nullptr;
}
Stack::~Stack()
{
    SNodePtr nextNode;

    while (top != nullptr) {
        nextNode = top->next;
        delete top;
        top = nextNode;
    }
}
cwjensen
  • 1
  • 2
  • "*Note that in the output there is no 'hello', which to me, seems like the error is in view*" - Actually, `cout` is typically line-buffered, and you are not writing a line break, or flushing the output buffer, before the error occurs. So `hello` is likely still in the output buffer when the program crashes. – Remy Lebeau Oct 03 '22 at 22:15
  • "*I'm fairly certain the error occurs somewhere in this copy constructor*" - Why is the copy constructor modifying the input `Stack` at all? It doesn't need to. It has direct access to the input `Stack`'s nodes. Just iterate the node list normally, `push`'ing its values into the new list. Same with `view()` and `peek()`, for that matter. `pop()` is not needed in them, either. In fact, they should both be marked as `const` to avoid modifying the `Stack` they are called on. Rem – Remy Lebeau Oct 03 '22 at 22:17
  • @Remy This is an assignment for a college class, with a particularly unhelpful professor. We were explicitly told to reuse pop and push for the copy constructor, view, and peek. – cwjensen Oct 03 '22 at 23:33
  • "*with a particularly unhelpful professor*" - that is an understatement. I would look for a new teacher. Or just get yourself some [decent C++ books](https://stackoverflow.com/questions/388242/) to learn from. – Remy Lebeau Oct 04 '22 at 00:15
  • 1
    In any case, when I run the code you have provided as-is (after filling in a couple of missing pieces needed to make it compile, namely the default constructor and the destructor), I do not get any error at all. Online demo: https://onlinegdb.com/zMbo45AiU. So please edit your question to provide a [mcve] that reproduces the error in action. – Remy Lebeau Oct 04 '22 at 00:20
  • @Remy Updated the question. After changing some of the code, the error switched to Segmentation Fault, which, I think (?) is progress. – cwjensen Oct 04 '22 at 15:41
  • A segfault in the destructor implies you are freeing invalid memory, such as after a violation of the Rule of 3/5/0. But offhand, all of the code shown so far (including code you have now removed) looks fine. Without a viable [mcve] demonstrating the actual error in action, it is very difficult to help you. – Remy Lebeau Oct 04 '22 at 18:02

0 Answers0