COMP: Move inline = default destructors to .cxx for 30 exported classes#6041
Conversation
Non-template exported classes with `~ClassName() override = default;` inline in the header have hidden D1Ev/D0Ev destructor thunks under -fvisibility-inlines-hidden, even when the class vtable and typeinfo remain exported. This breaks dynamic_cast across DSO boundaries in shared library builds. Moving the destructor definition out of line to the .cxx file ensures it is compiled in exactly one translation unit, giving it default (exported) visibility and correctly anchoring all destructor thunks. Affected modules: ITKCommon (3), ITKIOImageBase (3), ITKFEM (1), ITKOptimizers (11), ITKStatistics (8), ITKWatersheds (2), ITKVideoCore (1). See: InsightSoftwareConsortium#6000
|
| Filename | Overview |
|---|---|
| Modules/Core/Common/include/itkEquivalencyTable.h | Removes inline = default destructor; now declares ~EquivalencyTable() override; only — correct pattern |
| Modules/Core/Common/src/itkEquivalencyTable.cxx | Adds out-of-line EquivalencyTable::~EquivalencyTable() = default; — anchors destructor thunks correctly |
| Modules/Core/Common/include/itkLoggerManager.h | Inline = default destructor removed; declaration-only ~LoggerManager() override; retained — correct |
| Modules/Core/Common/src/itkLoggerManager.cxx | Out-of-line destructor added at top of translation unit — correct placement |
| Modules/Numerics/Optimizers/include/itkOptimizer.h | Declaration-only destructor ~Optimizer() override; — correct, consistent with the rest of the PR |
| Modules/Numerics/Optimizers/src/itkOptimizer.cxx | Out-of-line Optimizer::~Optimizer() = default; added — correctly anchors vtable and destructor thunks |
| Modules/Numerics/FEM/include/itkFEMLightObject.h | Declaration-only destructor left in header — correct fix for DSO visibility |
| Modules/Numerics/FEM/src/itkFEMLightObject.cxx | Out-of-line FEMLightObject::~FEMLightObject() = default; added inside nested itk::fem namespace — correct |
| Modules/Numerics/Statistics/src/itkChiSquareDistribution.cxx | Out-of-line destructor placed correctly before the constructor definition — matches established pattern |
| Modules/Video/Core/src/itkTemporalProcessObject.cxx | Out-of-line TemporalProcessObject::~TemporalProcessObject() = default; added — correct |
| Modules/Segmentation/Watersheds/src/itkOneWayEquivalencyTable.cxx | Out-of-line destructor definition added at top of namespace block — correct and consistent |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Class declared with ITK*_EXPORT macro\n(shared library build)"]
A --> B{Destructor placement?}
B -- "Before (inline = default in header)" --> C["Compiled into every TU that includes header\nfvisibility-inlines-hidden hides D1Ev/D0Ev thunks\nBreaks dynamic_cast across DSO boundaries"]
B -- "After (out-of-line = default in .cxx)" --> D["Compiled into exactly one TU\nDestructor has default (exported) visibility\nAll destructor thunks anchored and exported"]
C --> E["❌ dynamic_cast fails across DSO boundaries\n(shared library builds)"]
D --> F["✅ dynamic_cast works correctly\nacross DSO boundaries"]
Reviews (1): Last reviewed commit: "COMP: Move inline = default destructors ..." | Re-trigger Greptile
7330169
into
InsightSoftwareConsortium:release-5.4
Non-template exported classes with
~ClassName() override = default;inline in the header have hidden D1Ev/D0Ev destructor thunks under -fvisibility-inlines-hidden, even when the class vtable and typeinfo remain exported. This breaks dynamic_cast across DSO boundaries in shared library builds.Moving the destructor definition out of line to the .cxx file ensures it is compiled in exactly one translation unit, giving it default (exported) visibility and correctly anchoring all destructor thunks.
Affected modules: ITKCommon (3), ITKIOImageBase (3), ITKFEM (1), ITKOptimizers (11), ITKStatistics (8), ITKWatersheds (2), ITKVideoCore (1).
See: #6000
This is a backport to @hjmjohnson 's patch to ITK 5.