How to fix "Access violation reading" error?

-1

I set up a "parent class pointer" vector with size 2 to store its "derived class" address but seem like this vector only stores final address no matter how many address i added, so its cause "Access violation reading" problem. By the way i used composite pattern.

I've tried many ways, i've used vector, 2d pointer (Ex: int**).

class Node{
    public:
        virtual double evaluate();
};
class NumNode: public Node{
   private:
        double number;
    public:
        double evaluate();
        NumNode(int);
};
class OpNode: public Node{
    private:
        char operation;
        vector<Node*> branch;
    public:
        double evaluate();
        void addLeft(NumNode);
        void addRight(NumNode);
        OpNode(char);
};

double OpNode::evaluate(){
    if(this->operation == '+')
        return this->branch[0]->evaluate() + this->branch[1]- 
            >evaluate();**Exception thrown at 0x008C6097 in 
                          Project_Testing.exe: 0xC0000005: Access 
                          violation reading location 0xCCCCCCCC.**

return 0; 
}

void OpNode::addLeft(NumNode other){this->branch[0] = &other;}
void OpNode::addRight(NumNode other){this->branch[1] = &other;}

int main(){
    OpNode n('+');
    n.addLeft(NumNode(2));
    n.addRight(NumNode(3));
    cout << n.evaluate() << endl;
}

As you look into the main funciton, i've add two diffrent NumNode. But when i started debugging. branch[0] 0x006ff620 {...} Node * branch[1] 0x006ff620 {...} Node *. They had the same address!

c++
polymorphism
composite
asked on Stack Overflow Aug 26, 2019 by Nguyen Bot

2 Answers

0

You issue is here:

void OpNode::addLeft(NumNode other){this->branch[0] = &other;}
void OpNode::addRight(NumNode other){this->branch[1] = &other;}

As mentioned in comment:

Your addLeft and addRight take the address of the stack parameter other. Since the stack looks exactly same for both calls, you see exactly the same address. Either pass in a real pointer that can be stored directly, or (in your methods) allocate a copy (with new NumNode(other)) and store that address.

Another way around it you will probably wan't for nodes is using std::shared_ptr So your nord list becomes:

vector<shared_ptr<Node> > branch;

and then:

void OpNode::addLeft(const shared_ptr<NumNode> >& other){this->branch[0] = other;}
answered on Stack Overflow Aug 26, 2019 by darune
0

You are taking pointer to temporary object. When this objects lifetime ends referencing it is an Undefined Behavior, what in this case ends with a crash.

Create this objects on heap to extend lifetime of required objects.

For example:

class Node{
    public:
        virtual ~Node() {}
        virtual double evaluate();
};

class NumNode: public Node {
    private:
        double number;
    public:
        double evaluate();
        NumNode(int);
};

class BinaryOpNode: public Node{
    private:
        std::unique_ptr<Node> left;
        std::unique_ptr<Node> right;
    public:
        BinaryOpNode(std::unique_ptr<Node> a, std::unique_ptr<Node> b)
           : left{std::move(a)}
           , right{std::move(b)}
        {
        }

        double evaluate() {
           return binaryOperator(left->evaluate(), right->evaluate());
        }
        virtual double binaryOperator(double a, double b) = 0;
};

class AddOpNode : public BinaryOpNode {
public:
    using BinaryOpNode::BinaryOpNode;

    double binaryOperator(double a, double b) { return a + b; }
};

int main(){
    AddOpNode n {
        std::make_unique<NumNode>(2), 
        std::make_unique<NumNode>(3)
    };

    cout << n.evaluate() << endl;

    return 0;
}
answered on Stack Overflow Aug 26, 2019 by Marek R

User contributions licensed under CC BY-SA 3.0