Skip to content

fix(Print): add missing virtual destructor - #281

Open
saikumar-mandaji wants to merge 1 commit into
arduino:masterfrom
saikumar-mandaji:fix-print-missing-virtual-destructor
Open

fix(Print): add missing virtual destructor#281
saikumar-mandaji wants to merge 1 commit into
arduino:masterfrom
saikumar-mandaji:fix-print-missing-virtual-destructor

Conversation

@saikumar-mandaji

Copy link
Copy Markdown

Bug

Print is an abstract base class (virtual size_t write(uint8_t) = 0) used polymorphically throughout the core: any Stream/HardwareSerial/etc. is routinely held and deleted through a Print* or Stream*. With no virtual destructor, delete-ing such an object through a base pointer is undefined behavior — the derived class's destructor (and therefore its members' destructors) never runs.

This isn't hypothetical: it was already observed producing a real -Wdelete-non-virtual-dtor warning in a shipping Arduino core (Renesas Uno R4's WiFiS3/src/Modem.cpp, deleting a UART through a Serial/Print-derived pointer) — see #256.

Fix

Add virtual ~Print() { }, matching the inline empty-body style already used for this exact purpose on other polymorphic base classes in this repo (CanMsg, HardwareCAN, HardwareSPI).

Since Print already has a pure virtual write() and therefore already carries a vtable pointer in every instance, this adds no per-instance memory cost on 8-bit AVR or any other target — only one additional vtable entry (a few bytes in flash).

Verification

Compiled a minimal Stream-derived class with arm-none-eabi-g++ -std=gnu++14 -Wall -Wextra -Wdelete-non-virtual-dtor (no host-native compiler was available in this environment): before this change, delete-ing it through a Print* triggers -Wdelete-non-virtual-dtor; after, the warning is gone. Also confirmed a Print-derived class still compiles cleanly with the added destructor.

Did not run this repo's own host test suite (needs a native g++/clang, not present in this environment) — flagging that honestly rather than claiming a full test-suite pass.

Fixes #256

Print is an abstract base class (virtual size_t write(uint8_t) = 0)
used polymorphically throughout the core: any Stream/HardwareSerial/
etc. is routinely held and deleted through a Print* or Stream*. With
no virtual destructor, 'delete'-ing such an object through a base
pointer is undefined behavior -- the derived class's destructor
(and therefore its members' destructors) never runs.

This isn't hypothetical: it was already observed producing a real
-Wdelete-non-virtual-dtor warning in a shipping Arduino core (R4's
WiFiS3 Modem.cpp, deleting a UART through a Serial/Print-derived
pointer), see arduino#256.

Fix: add 'virtual ~Print() { }', matching the inline empty-body style
already used for this exact purpose on other polymorphic base classes
in this repo (CanMsg, HardwareCAN, HardwareSPI).

Since Print already has a pure virtual write() and therefore already
carries a vtable pointer in every instance, this adds no per-instance
memory cost on 8-bit AVR or any other target -- only one additional
vtable entry.

## Verification

Compiled a minimal Stream-derived class with
'arm-none-eabi-g++ -std=gnu++14 -Wall -Wextra -Wdelete-non-virtual-dtor'
(no host-native compiler was available in this environment):
before this change, 'delete'-ing it through a Print* triggers
-Wdelete-non-virtual-dtor; after, the warning is gone. Also confirmed
a Print-derived class still compiles cleanly with the added
destructor. Did not run ArduinoCore-API's own host test suite (it
needs a native g++/clang, not present here).

Fixes arduino#256
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing virtual destructor for Print class

1 participant