What’s the difference between `alloc::alloc::Global` and `std::alloc::System`?

The former uses internal alloc API, and the latter uses system alloc API. Vec, Box uses the former.
Is the former implicitly replaced by the latter when there is std? What is the internal alloc API when there is std?

The former impls core::alloc::Allocator, the latter impls core::alloc::GlobalAlloc, but there is neither impl<T: Allocator> for GlobalAlloc nor impl<T: GlobalAlloc> for Allocator.

Before we go any further: the core and alloc crates are (almost completely) subsets of std. So don't worry about the crate name — the modules are the same regardless of which crate you access them from, except that some items are only in alloc or only in std and not in core.

Now, about the types:

  • Suppose you are thinking about choosing or implementing the global memory allocator used by Rust code by default. In this case, you care about the GlobalAlloc trait.

    • To implement a global allocator, you implement GlobalAlloc.
    • To choose the global allocator your program uses, you use the #[global_allocator] attribute to declare the desired allocator, which must implement GlobalAlloc.
      • std::alloc::System exists so that you can explicitly choose the system allocator, or can wrap it to add behavior (as noted in the documentation for that type).
  • Suppose you want to use “local” allocators that are not the declared global allocator. In that case, you care about the std::alloc::Allocator trait and its implementors. (Note that all of this is still unstable, nightly-only).

    • std::alloc::System implements Allocator, so you can use specifically the system allocator, regardless of what the global allocator is.
    • std::alloc::Global implements Allocator, so you can use the registered global allocator.
    • You can also use an Allocator implementation that is neither of the above.

Is the former implicitly replaced by the latter when there is std?

The difference between “std” and “no std” environments is that the latter

  • have no std::alloc::System since they don't have std and that's one of the items not in the alloc crate, and
  • have no #[global_allocator] declared, so if you want to use a global allocator without std you have to declare one yourself.

But the traits are the same, and Global exists in the alloc crate, so you can use it as an Allocator if you declare a global allocator.

The former impls core::alloc::Allocator, the latter impls core::alloc::GlobalAlloc, but there is neither impl<T: Allocator> for GlobalAlloc nor impl<T: GlobalAlloc> for Allocator.

Right. The only way GlobalAllocs get used is as #[global_allocator]. There is always exactly one of those. Then, if you want an Allocator that is the global allocator, you don't pass an instance of it — you pass Global which does implement Allocator.


Note that all of this except for GlobalAlloc and System is unstable — because it's not certain that it's the right design yet. What I've written above is how it currently works.

8 Likes

Haven't noticed this before.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.