ABI Safety
Questo contenuto non è ancora disponibile nella tua lingua.
ABI safety is a hard requirement for Saturn when distributed as a dynamic library. Public engine binaries must remain link-compatible across projects and machines without forcing consumers to rebuild the engine.
Breaking ABI compatibility leads to undefined behavior that is often silent, difficult to diagnose, and catastrophic at runtime. These rules exist to prevent that class of failure.
What ABI Means in Practice
Section titled “What ABI Means in Practice”The Application Binary Interface (ABI) defines how compiled code interacts at the binary level. It governs:
-
Calling conventions How functions are invoked, how arguments are passed, and how return values are produced.
-
Object layout Memory layout of classes and structs, including padding, alignment, and member ordering.
-
Virtual dispatch VTable layout and virtual function resolution.
-
Exceptions and RTTI Binary representation of exceptions and runtime type information.
ABI compatibility depends on:
- Compiler vendor and version
- Compiler flags and standard library implementation
- Target architecture
- Build configuration (Debug vs Release)
A mismatch in any of these can invalidate binary compatibility even when source code appears unchanged.
Objects That Must Not Cross DLL Boundaries
Section titled “Objects That Must Not Cross DLL Boundaries”The following constructs are ABI-unsafe and must not appear in public engine APIs.
Standard Library Types
Section titled “Standard Library Types”- Any type from
std(containers, strings, smart pointers, function wrappers) - Types that embed or expose STL internals
Standard library implementations are not ABI-stable across compiler versions or CRTs.
Ownership-Sensitive Objects
Section titled “Ownership-Sensitive Objects”- Objects constructed in the library and destroyed in the client
- Objects destroyed by a different allocator than the one that created them
Cross-boundary allocation or destruction results in undefined behavior.
Exposed Internal Layout
Section titled “Exposed Internal Layout”- Inline methods that reference private members
- Headers that expose internal structs, templates, or implementation headers
Even inline accessors can leak ABI if they expose layout or template instantiations.
Exceptions and RTTI
Section titled “Exceptions and RTTI”- Throwing exceptions across the DLL boundary
- Using
dynamic_castortypeidacross boundaries
These are only safe when compiler, standard library, and runtime are strictly identical—and should be avoided regardless.
Approved ABI-Safe Patterns
Section titled “Approved ABI-Safe Patterns”Opaque Handles (PIMPL)
Section titled “Opaque Handles (PIMPL)”Use opaque pointers to incomplete types as the primary mechanism for ABI isolation.
- Public headers declare an incomplete
Impl - All data members live in the source file
- Public methods forward to the implementation
This isolates layout changes from consumers and is the preferred pattern in Saturn.
Value Copies
Section titled “Value Copies”Returning or accepting copied values is ABI-safe only when:
- The type is trivially copyable, or
- Construction and destruction occur on the same side
Const Accessors
Section titled “Const Accessors”const references or views are generally safe when:
- They do not imply ownership transfer
- They do not expose internal layout assumptions
Ownership Rules (Mandatory)
Section titled “Ownership Rules (Mandatory)”To maintain ABI safety, ownership must be explicit and respected:
- Objects created by the library are destroyed by the library
- Objects created by the client are destroyed by the client
- Ownership transfer must be explicit and documented
- Internal state must not be mutated through client-owned pointers
When in doubt, return handles or copies—not references.
Virtual Functions and ABI Stability
Section titled “Virtual Functions and ABI Stability”Virtual functions form part of the ABI contract.
Rules:
- Never remove or reorder public virtual functions
- Never change the signature of an existing virtual function
- New virtual functions must be appended to the end of the vtable
- ABI-breaking changes require versioned binaries
Virtual interfaces should be treated as frozen contracts once released.
Singletons and Static State
Section titled “Singletons and Static State”- Static objects must be owned entirely by the DLL
- Clients must never construct or destruct static engine objects
- Access must be provided via exported functions or accessors
This prevents cross-runtime lifetime mismatches.
Platform and Toolchain Constraints
Section titled “Platform and Toolchain Constraints”ABI compatibility is not portable by default.
Expect differences across:
- Compiler vendors (MSVC, Clang, GCC)
- Compiler versions
- CRT versions
- Architectures
- Build modes
Saturn does not attempt to guarantee ABI compatibility across incompatible toolchains. Consumers are expected to use supported configurations.
Testing and Versioning
Section titled “Testing and Versioning”ABI stability must be verified continuously.
Recommended tools:
abi-compliance-checkernm,readelf,objdumpdumpbin(Windows)
Any ABI-breaking change must:
- Be detected automatically
- Be documented
- Trigger a version bump
Pragmatic Exceptions
Section titled “Pragmatic Exceptions”Some designs may require controlled ABI violations.
When this occurs:
- Scope must be minimal
- Exposure must be tightly audited
- Exceptions must be documented explicitly
- Rebuild requirements must be clearly stated
ABI safety is the default. Exceptions are deliberate, rare, and visible.
Design Principle
Section titled “Design Principle”ABI rules exist to protect users from undefined behavior, not to constrain design unnecessarily.
When choosing between convenience and binary safety, Saturn always favors explicitness, isolation, and long-term stability.