What is causing zsh:segmentation fault in this case?

574 Views Asked by At

this is my first every time posting a question on stackoverflow so I apologize beforehand If my question seems messy. I have a class named token, and a derived class from it called function, integer, and operator. Token has a public variable of type int called _type. I assigned different _type values for each derived classes. The type for integer is 1, 2 for operator, and 3 for function. The purpose of this is so that I can implement different operations depending on the type encountered. I made an rpn function and in it I have something like this.

double RPN::rpn(){
     
    Stack<Token*> rpn_stack;

    while(input_q.empty() == false){

        if(input_q.front()->_type == 1){

            rpn_stack.push(input_q.pop());
        }

        if(input_q.front()->_type == 2){

            double x = rpn_stack.pop()->value();
            double y = rpn_stack.pop()->value();

            //cout << x << y;

            char i = input_q.pop()->op();

            if(i == '*'){

                double result;
                result = x * y;
                rpn_stack.push(new Integer(result));

            }
        }

        if(input_q.front()->_type == 3){

            input_q.pop();
            rpn_stack.push(new Integer(_val));
           
        }
     }
     return rpn_stack.top()->value();
}

after testing it a couple of times, I found out that the zsh:segmentation fault problem is caused by the input_q.pop() in

        if(input_q.front()->_type == 3){

            input_q.pop();
            rpn_stack.push(new Integer(_val));
           
        }

However, the code works if I change the order of the if statements like this

double RPN::rpn(){
     
    Stack<Token*> rpn_stack;

    while(input_q.empty() == false){

        if(input_q.front()->_type == 3){

            input_q.pop();
            rpn_stack.push(new Integer(_val));
           
        }

        if(input_q.front()->_type == 1){

            rpn_stack.push(input_q.pop());
        }

        if(input_q.front()->_type == 2){

            double x = rpn_stack.pop()->value();
            double y = rpn_stack.pop()->value();

            //cout << x << y;

            char i = input_q.pop()->op();

            if(i == '*'){

                double result;
                result = x * y;
                rpn_stack.push(new Integer(result));

            }
        }
     }
     return rpn_stack.top()->value();
}

which leads me to question whether the problem was input_q.pop() in the first place. It also works if I were to assign input_q.front()->_type to a static variable inside the while loop like this

double RPN::rpn(){
     
    Stack<Token*> rpn_stack;

    while(input_q.empty() == false){

        int type = input_q.front()->_type;

        if(type == 1){

            rpn_stack.push(input_q.pop());
        }

        if(type == 2){

            double x = rpn_stack.pop()->value();
            double y = rpn_stack.pop()->value();

            //cout << x << y;

            char i = input_q.pop()->op();

            if(i == '*'){

                double result;
                result = x * y;
                rpn_stack.push(new Integer(result));

            }
        }

        if(type == 3){

            input_q.pop();
            rpn_stack.push(new Integer(_val));
           
        }
       
    }
    return rpn_stack.top()->value();
}

At this point I am very confused as to what is causing zsh:segmentation fault when using the first version. Im wondering if the problem lies in accessing input_q.front()->_type? I could just use the second and third version but I really want to know what is causing zsh:segmentation fault on the first version. If it helps, here is the simple program I wrote to test it. I am also using stack and queue if it helps.

    Queue<Token *> postfix;
    postfix.push(new Integer(3));
    postfix.push(new Integer(5));
    postfix.push(new Operator("*"));
    RPN rpn(postfix);
    cout << "3 5 *: " << rpn() << endl;
    cout << "-------------" << endl;
    Queue<Token *> postfix2;
    postfix2.push(new Integer(3));
    postfix2.push(new Function("X"));
    postfix2.push(new Operator("*"));
    rpn.set_input(postfix2);
    cout << "3 x *: (x=3): " << rpn(3) << endl;

the rpn function is called using the () operator in the RPN class. the RPN class has a private variable called _val that is assigned a value to by the () operator. Hope the information Ive provided is enough. Thank you for your time, would appreciate the input!

1

There are 1 best solutions below

1
Paul Sanders On

With reference to your first code snippet, when you say this:

if(input_q.front()->_type == 1){
    rpn_stack.push(input_q.pop());
}

if(input_q.front()->_type == 2){
...

You don't check if there's anything left on the input queue the second time you call input_q.front.

A simple fix is to insert a continue statement, like this:

if(input_q.front()->_type == 1){
    rpn_stack.push(input_q.pop());
    continue;
}

...

You will then loop back to the while statement which checks whether the queue is empty before proceeding.

There are other places in the code where you need to make a similar change, but you get the idea.