Vai al contenuto

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.


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.

  • 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.


  • 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.


  • 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.


  • Throwing exceptions across the DLL boundary
  • Using dynamic_cast or typeid across boundaries

These are only safe when compiler, standard library, and runtime are strictly identical—and should be avoided regardless.


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.


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 references or views are generally safe when:

  • They do not imply ownership transfer
  • They do not expose internal layout assumptions

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 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.


  • 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.


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.


ABI stability must be verified continuously.

Recommended tools:

  • abi-compliance-checker
  • nm, readelf, objdump
  • dumpbin (Windows)

Any ABI-breaking change must:

  • Be detected automatically
  • Be documented
  • Trigger a version bump

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.


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.