Skip to content

Fix freestanding no malloc guards - #4

Merged
patkenneally merged 2 commits into
feature/freestandingfrom
fix/freestanding-no-malloc-guards
Aug 25, 2026
Merged

patkenneally merged 2 commits into
feature/freestandingfrom
fix/freestanding-no-malloc-guards

Conversation

@patkenneally

@patkenneally patkenneally commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Make EIGEN_NO_MALLOC mean something in release builds

Two independent fixes to freestanding Eigen, found while investigating four -Wreturn-type warnings in a riscv32-elf-g++ -Os -DNDEBUG build.

  1. Delete the EIGEN_NO_MALLOC allocation entry points instead of asserting
    Memory.h guarded six allocators with bodies that contained only eigen_assert(false && "heap allocation is forbidden"). Under NDEBUG, eigen_plain_assert expands to nothing (Macros.h:1004-1017), so those became empty functions returning void* - undefined behaviour if ever called.

This is NDEBUG-specific rather than target-specific: it reproduces on a host with g++-13 -DEIGEN_FREESTANDING=1 -DNDEBUG and disappears without -DNDEBUG.

The six (handmade_aligned_malloc/free/realloc,conditional_aligned_malloc/free/realloc<false>) are now deleted declarations under EIGEN_NO_MALLOC. No body means no warning and no fall-through, and any real use becomes a compile error naming the caller.

Safe to delete: in freestanding EIGEN_DEFAULT_ALIGN_BYTES == 0, so aligned_malloc takes the plain-malloc branch and never reaches handmade_aligned_*. Running nm on compiled products confirms none of these symbols are referenced.

  1. Define alloca as a macro so Eigen detects it

Freestanding/portable_stdlib.h declared alloca as an extern "C" function, but Eigen selects its stack-allocation path with #if ... || (defined alloca)
(Memory.h:613) — a macro test, which a declaration never satisfies.

Consequence: EIGEN_ALLOCA stayed undefined on the freestanding target, so ei_declare_aligned_stack_constructed_variable fell to the #else branch at Memory.h:794, which calls aligned_malloc unconditionally, at any size, with no EIGEN_STACK_ALLOCATION_LIMIT check. Hosted builds have alloca and keep small temporaries on the stack, which is why this never showed up there.

Replaced with #define alloca __builtin_alloca, which GCC emits inline on every target including RISC-V. Verified EIGEN_ALLOCA is now defined under riscv32-elf-g++ -ffreestanding.

EIGEN_STACK_ALLOCATION_LIMIT is deliberately left at its default: it is overloaded between that ternary and a static assert capping fixed-size stack objects (DenseStorage.h:33), so tuning it for one breaks the other.

Scope

Both changes are inside #ifdef EIGEN_NO_MALLOC / the freestanding branch. The #else paths keep the original definitions, so hosted and normal Eigen builds are untouched.

Testing

-fsyntax-only on <Eigen/Dense> clean in three configurations: RV32 freestanding -Os -DNDEBUG, RV32 freestanding -Og, and hosted -O2 plain Eigen.

@patkenneally
patkenneally merged commit 720162d into feature/freestanding Aug 25, 2026
4 checks passed
@patkenneally
patkenneally deleted the fix/freestanding-no-malloc-guards branch August 25, 2026 17:51
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.

1 participant