简体   繁体   中英

Different behaviour with calling functions inside and outside objects

Some very weird behaviour is happening with my C++ code. I have a function backward() in my MultiplyOperation class that I call from another object FloatTensor class which has an instance of this MultiplyOperation class.

The result of the output is different if I call three.backOperation->backward(1); and three.backOperation->backward(1); whereas it should be same. Please help.

This is my code:

#include<iostream>
using namespace std; 

class FloatTensor;

class MultiplyOperation{
     public:
        FloatTensor *t1, *t2; 
        float grad = 10;

        MultiplyOperation(FloatTensor* t1, FloatTensor* t2);

        FloatTensor compute();

        void backward(float gradient);
};

class FloatTensor {
    public:
    float val; 
    float grad; 
    MultiplyOperation* backOperation = NULL, *frontOperation = NULL;

    FloatTensor() {
        // default
    }

    FloatTensor(float value) {
        this->val = value;
        this->backOperation = NULL;
    }

    FloatTensor(float value, MultiplyOperation* backOp) {
        this->val = value;
        this->backOperation = backOp;
    }

    void backward(float gradient) {
        this->backOperation->backward(gradient);
    }


    FloatTensor operator * (FloatTensor two) { 
        MultiplyOperation ope(this,&two);
        this->frontOperation = &ope;
        return this->frontOperation->compute();
    }
};


MultiplyOperation::MultiplyOperation(FloatTensor* te1, FloatTensor* te2) {
    this->t1 = te1;
    this->t2 = te2;
}

FloatTensor MultiplyOperation::compute() {
    return FloatTensor(this->t1->val*this->t2->val, this);
}

void MultiplyOperation::backward(float gradient) {

    cout<<this->t2->val<<endl;
}


int main() {

    FloatTensor one(2);
    FloatTensor two(4);

    FloatTensor three = one*two;

    three.backOperation->backward(1); // should be same as output of next line and is 4. (which is correct)
    three.backward(1); // should be same as output of above line but is garbage value -4.12131 

}

Your program has undefined behavior because of the following function:

FloatTensor operator * (FloatTensor two) { 
   MultiplyOperation ope(this,&two);
   this->frontOperation = &ope;
   return this->frontOperation->compute();
}

You are storing a pointer to an object, ope , that is no longer valid once the function returns.

The same problem exists with the use of two in creating ope .

You can change the function to store a pointer to a dynamically allocated object to resolve that problem.

FloatTensor operator * (FloatTensor two) { 
   this->frontOperation = new MultiplyOperation(this, new FloatTensor(two));
   return this->frontOperation->compute();
}

or use

FloatTensor operator * (FloatTensor& two) { 
   this->frontOperation = new MultiplyOperation(this, &two);
   return this->frontOperation->compute();
}

Please note that it will be better to use smart pointers instead of raw pointers. Otherwise, your program will continue to have the risk of running into more memory related problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM