I have a simple abstract base class:
class Sensor {
protected:
GenericDriver *driver;
public:
Sensor() {};
virtual void startNewReadout(void) = 0;
};
From which I derive a concrete class:
class OneWireSensor : public Sensor {
private:
OneWireDriver oneWireDriver; //not really necessary here
public:
OneWireSensor(PinData *pinData);
void startNewReadout(void){
this->driver->driverStartReadout();
}
};
Now, when I use the below constructor, my code compiles and runs just as expected:
OneWireSensor::OneWireSensor(PinData *pinData) : oneWireDriver(OneWireDriver(pinData)) {
this->driver = &oneWireDriver;
}
However, the field oneWireDriver is not used anywhere in my code and I don't want to set it. But when I remove it from the OneWireSensor class and use a constructor as follows:
OneWireSensor::OneWireSensor(PinData *pinData) {
OneWireDriver oneWireDriver(pinData);
this->driver = &oneWireDriver;
}
The code compiles fine but the execution ends in a runtime exception (a system hard fault since I am on embedded). GenericDriver is an abstract class from which OneWireDriver class inherits. What am I doing wrong in the second case?
The problem is most likely caused by the dangling pointer from the constructor of OneWireSensor
.
OneWireSensor::OneWireSensor(PinData *pinData) {
// A function local object.
OneWireDriver oneWireDriver(pinData);
// Pointer to the function local object.
// It becomes a dangline pointer as soon as the function returns.
this->driver = &oneWireDriver;
}
You need to use a dynamically allocated object.
OneWireSensor::OneWireSensor(PinData *pinData) {
this->driver = new OneWireDriver(pinData);
}
But then you'll have to write code to manage the dynamically allocated memory. It'll be better to use a smart pointer instead of a raw pointer. See https://en.cppreference.com/w/cpp/memory for more on smart pointers.