I am sending a polymorphic object over serial between two Arduinos. The transmission should be fine, indeed if on the receiver side I static_cast
the pointer to the Derived
class it works properly. On the other hand if I try to call virtual functions on the Base
pointer, Arduino resets. What is causing this behaviour?
Some samples of the code follows.
Sender:
RS485_Serial bus;
void loop ()
{
Random r(1); //targeting device 1 in the bus
if (r.request(bus)) { blink(r.val); } //make a request for a random number
//blink the led the given number of times
delay(1000);
}
Receiver:
RS485_Serial bus;
bus.set_address(1);
void loop ()
{
listen(bus);
}
Selected common parts:
struct Action {
byte target_address;
Action(byte addr): target_address(addr) {}
virtual ~Action() {}
virtual size_t size() const { return sizeof(*this); }
virtual int vrequest(RS485_Serial &) = 0;
virtual void vrespond(RS485_Serial &) = 0;
int request(RS485_Serial & bus) {
bus.write(reinterpret_cast<byte*>(this), size());
return vrequest(bus);
}
void respond(RS485_Serial & bus) {
vrespond(bus); // <--- This virtual call makes the sender reset
}
};
struct Random: Action {
size_t size() const override { return sizeof(*this); }
int val;
Random(byte address): Action(address) {}
int vrequest(RS485_Serial & bus) override {
return bus.read(val);
}
void vrespond(RS485_Serial & bus) override {
bus.write(static_cast<decltype(val)>(random(2,5)));
}
};
void listen(RS485_Serial & bus) {
byte * data = nullptr;
byte length = 0;
if ( bus.read(data, length) ){
Action & a = *(reinterpret_cast<Action*>(data));
if (a.size() == length) blink(3);
if (a.target_address == bus.address) {
a.respond(bus);
//static_cast<Random*>(&a)->vrespond(); works but it has no point
}
}
}
My doubt is that if the vtable is stored in different positions, than the vtable pointer in the object obtained by the receiver will be off, causing the crash.