119. Borrowed Interface Lifetime Safety

#include <iostream>
using namespace std;

class Driver {
public:
    virtual void transfer() = 0;
    virtual ~Driver() {}
};

class SpiDriver : public Driver {
public:
    void transfer() override {
        cout << "SPI transfer completed" << endl;
    }
};

class I2cDriver : public Driver {
public:
    void transfer() override {
        cout << "I2C transfer completed" << endl;
    }
};

Driver* g_driver = nullptr;

void registerDriver(Driver& driver) {
    g_driver = &driver;
}

void frameworkRun() {
    g_driver->transfer();
}

int main() {
    int mode;
    cin >> mode;

    // Ensure driver lifetime exceeds framework usage
    SpiDriver spi;
    I2cDriver i2c;

    if (mode == 0) {
        registerDriver(spi);
    } else {
        registerDriver(i2c);
    }

    frameworkRun();

    return 0;
}

Explanation & Logic Summary

  • The framework stores a borrowed base-class pointer
  • In the original design, the driver object was destroyed when leaving the if block
  • This left g_driver pointing to a destroyed object (dangling pointer)
  • The corrected design ensures:
    • Driver objects live at least as long as framework usage
    • No heap allocation is required
    • Runtime polymorphism is preserved safely

This enforces a critical embedded rule:

Borrowed interfaces must never outlive the owning object.

Firmware Relevance & Real-World Context

In real embedded firmware:

  • Drivers are often registered with:
    • Frameworks
    • Protocol stacks
    • Schedulers or ISR dispatchers
  • These systems frequently store non-owning pointers to drivers
  • If lifetime rules are violated, the result can be:
    • Random crashes
    • Peripheral corruption
    • Intermittent, hard-to-debug field failures

This problem trains developers to recognize and fix lifetime-related polymorphism bugs, a core skill in safe embedded C++ design.

 

 

 

 

Loading...

Input

0

Expected Output

SPI transfer completed