Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link against alloc without global allocator #123

Open
wyager opened this issue Mar 6, 2024 · 1 comment
Open

Link against alloc without global allocator #123

wyager opened this issue Mar 6, 2024 · 1 comment

Comments

@wyager
Copy link

wyager commented Mar 6, 2024

Not sure if this is the right place to ask, but seems like a likely candidate.

Right now, if you link against alloc without having a global allocator, the linker fails with

no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait

However, my use case of alloc is exclusively via the _in APIs; I'm only using (non-global) arena allocators.

I'm currently working around this by having a dummy global allocator, but this is not ideal for a couple reasons:

  1. I might accidentally use the global alloc new API for some alloc type in a random codepath, and it won't fail until runtime
  2. I might pull in a dependency that advertises no_std, but deep in its bowels it actually invokes the global allocator in a rarely-used codepath, causing a surprise panic at runtime. That's not hypothetical - it actually happened with one of my current project's dependencies and I had to fork it to remove any linkages against alloc.

Ideally, we would defer linker failure to the absolute last minute, so the compilation only fails if a global allocator is actually referenced in the linked binary, rather than pessimistically fail just because I'm pulling in alloc.

Is this on anyone's radar? I'm not sure if my use case (embedded programming with only non-global allocators) is representative - this might be kind of an uncommon failure mode when linking against alloc.

@wyager
Copy link
Author

wyager commented Mar 7, 2024

Someone on IRC suggested this strategy, which works perfectly.

struct FakeAllocator;

unsafe impl core::alloc::GlobalAlloc for FakeAllocator {
    unsafe fn alloc(&self, layout: core::alloc::Layout) -> *mut u8 {
        extern "Rust" {
            fn fake_alloc_this_doesnt_exist(layout: core::alloc::Layout) -> *mut u8;
        }
        fake_alloc_this_doesnt_exist(layout)
    }
    unsafe fn dealloc(&self, ptr: *mut u8, layout: core::alloc::Layout) {
        extern "Rust" {
            fn fake_dealloc_this_doesnt_exist(ptr: *mut u8, layout: core::alloc::Layout);
        }
        fake_dealloc_this_doesnt_exist(ptr, layout)
    }
}

#[global_allocator]
static ALLOCATOR: FakeAllocator = FakeAllocator;

If I don't have any global allocs, it links fine. If I add one, linking fails with note: rust-lld: error: undefined symbol: fake_dealloc_this_doesnt_exist

This makes me think that this might actually be an easier technical issue than I thought. Perhaps we can just eliminate whatever check is emitting the no global memory allocator found message and let the linker error out?

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

No branches or pull requests

1 participant