# Pre-RFC: Support using the Rust allocator from C

**URL:** https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097
**Category:** language design
**Created:** [July 28, 2021, 11:44am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097 "2021-07-28T11:44:45Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [July 28, 2021, 11:44am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/1 "2021-07-28T11:44:46Z")

</div>

# Summary

Make the Rust allocator callable from C.

# Motivation

When using both C/C++ and Rust in the same project, it can be necessary to create Rust `Box`'es, `Vec`'s and `String`'s. As the Rust code may use an allocator other than `malloc`, it is not allowed to use `malloc` on the C/C++ side. Instead the Rust allocator needs to be called. Currently this requires everyone to individually creating wrapper functions on the Rust side that export a C interface. It would be much easier to allow directly using the Rust allocator from C/C++.

# Guide-level explanation

It becomes possible to allocate and free memory using the Rust allocator in C/C++ code linking to Rust code. This is useful when interacting a lot between Rust and C/C++ code. For example:

```rust
void *_RNvNtC4rust5alloc5alloc(size_t, size_t);
bool rust_box_is_42(uint32_t *);

bool box_is_42(uint32_t val) {
    uint32_t *box_ptr = _RNvNtC4rust5alloc5alloc(sizeof(uint32_t), alignof(uint32_t));
    rust_box_is_42(box_ptr);
}

```

```rust
#[no_mangle]
unsafe extern "C" fn rust_box_is_42(box_ptr: *const u32) -> bool {
    // `Box::from_raw` would not be allowed if `box_ptr` was allocated using `malloc`.
    let box_ = Box::from_raw(box_ptr);
    *box_ == 42
}

```

Or the other way around:

```rust
void _RNvNtC4rust5alloc7dealloc(void *, size_t, size_t);
uint32_t *get_rust_boxed_num();

bool box_is_42() {
    uint32_t *box = get_rust_boxed_num();
    bool is_42 = *box == 42;
    // It would not be valid to free `box` using `free`.
    _RNvNtC4rust5alloc7dealloc(box, sizeof(uint32_t), alignof(uint32_t));
    return is_42;
}

```

```rust
#[no_mangle]
extern "C" fn get_rust_boxed_num() -> *const u32 {
    Box::into_raw(Box::new(rand()))
}

```

It is **not** allowed to override (or define) any of the allocator symbols yourself, whether in C or Rust. They must always be defined by rustc through either `#[global_allocator]` or libstd.

# Reference-level explanation

The following functions will be exported that forward to the global Rust allocator:

```rust
#[linkage_name = "_RNvNtC4rust5alloc5alloc"]
extern "C" fn alloc(size: usize, align: usize) -> *mut u8;

#[linkage_name = "_RNvNtC4rust5alloc11alloc_zeroed"]
extern "C" fn alloc_zeroed(size: usize, align: usize) -> *mut u8;

#[linkage_name = "_RNvNtC4rust5alloc7realloc"]
extern "C" fn realloc(ptr: *mut u8, size: usize, align: usize) -> *mut u8;

#[linkage_name = "_RNvNtC4rust5alloc7dealloc"]
extern "C" fn dealloc(ptr: *mut u8, size: usize, align: usize);

```

These functions directly correspond to the respective methods on `GlobalAlloc`. All functions have the same safety invariants as the corresponding methods on `GlobalAlloc`. In addition the safety invariants of `Layout::from_size_align` must be followed when called with the given `size` and `align`.

These functions are directly visible to all code statically linked into a rust executable or shared library that depends on `liballoc` and all code that links to either `libstd.so` or a shared library that contains `#[global_allocator]`. They will always be available at runtime when `liballoc` is linked in, but it may be necessary to tell the linker that it is fine if it can't immediately find the allocator symbols using for example `--undefined`.

This RFC can be implemented by renaming the methods of the allocator shim and then adding documentation that the signatures of the functions in the allocator shim must not change.

# Drawbacks

Why should we _not_ do this?

# Rationale and alternatives

The function signature of these functions is already effectively stable as they correspond 1-to-1 with methods on the stable `GlobalAlloc`.

The OOM handling functions could also be stably exported, but given that defining the OOM handler isn't stable yet anyway and there are several design choices there that would affect the possibly exported C api, this RFC does not propose to export a C api for the OOM handler.

It would be possible to not export these functions. This is the status quo. It however requires everyone to write their own wrapper functions.

# Prior art

C/C++ allow directly calling the global allocator from other languages using `malloc` and `free`. Many "managed" languages like Python or Java also allow directly using the global allocator to allocate native objects using a C api.

# Unresolved questions

What name should be used? @eddyb suggested the names used in this RFC in [https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/upstreaming.20LLVM.20patch.20for.20\_\_rust\_.20alloc.20functions/near/247438389](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/upstreaming.20LLVM.20patch.20for.20__rust_.20alloc.20functions/near/247438389) such that backtraces look nice and it is clear that the functions are coming from Rust and not C or C++. It would also be possible to use names like `__rust_alloc` and ` __rust_dealloc` or `__ rustalloc_alloc` and `__rustalloc_dealloc`. These have the advantage of being easier to memorize and looking less weird.

Should the `extern "C"` or `extern "C-unwind"` abi be used. In other words, should these functions be allowed to unwind in the future.

How do we ensure that `--undefined` is never necessary to allow linking to succeed?

# Future possibilities

None that I know of.

---

<div class="post-metadata">

### Author: ![jyn514](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jyn514/32/13245_2.png) [@jyn514](https://internals.rust-lang.org/u/jyn514)
#### Post date: [July 28, 2021, 11:57am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/2 "2021-07-28T11:57:42Z")

</div>

Using the mangled symbols on the C++ side looks a little painful (I understand it's necessary for C, though). Could we add support for Rust symbol mangling to the C++ standard somehow, so you could use `extern "Rust" rust::alloc::alloc;`? I guess that would be a bad idea until the v0 symbol mangling finally gets upstreamed 🤞 but maybe after that?

---

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [July 28, 2021, 12:03pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/3 "2021-07-28T12:03:35Z")

</div>

I think the following would work as header file:

```cpp
namespace {
extern "C" {
    void *_RNvNtC4rust5alloc5alloc(size_t, size_t);
    void *_RNvNtC4rust5alloc11alloc_zeroed(size_t, size_t);
    void *_RNvNtC4rust5alloc7realloc(void *, size_t, size_t);
    void _RNvNtC4rust5alloc7dealloc(void *, size_t, size_t);
}
}

namespace rust {
namespace alloc {
using alloc = _RNvNtC4rust5alloc5alloc;
using alloc_zeroed = _RNvNtC4rust5alloc11alloc_zeroed;
using realloc = _RNvNtC4rust5alloc7realloc;
using dealloc = _RNvNtC4rust5alloc7dealloc;

}
}

```

You need a header file to specify the function signature anyway.

---

<div class="post-metadata">

### Author: ![InfernoDeity](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/infernodeity/32/7588_2.png) [@InfernoDeity](https://internals.rust-lang.org/u/InfernoDeity)
#### Post date: [July 28, 2021, 1:55pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/4 "2021-07-28T13:55:08Z")

</div>

> [@jyn514](#):
>
> Could we add support for Rust symbol mangling to the C++ standard somehow, so you could use `extern "Rust" rust::alloc::alloc;` ? I guess that would be a bad idea until the v0 symbol mangling finally gets upstreamed 🤞 but maybe after that?

Wouldn't need to be in the standard. An implementation could always support the `"Rust"` language linkage. For example:

```c++
namespace rust::alloc{
    extern"Rust" unsigned char* alloc(size: unsigned long,align: unsigned long);
}

```

would allow a C++ implementation that is aware of names from a particular rust implementation to mangle that symbol according to the rust name. I actually intend to do this in lccc, though it also adjusts the ABI to the "Rust" abi as well (so it would have to be exported in rust as `extern"Rust"` to work properly).

> [@bjorn3](#):
>
> What name should be used

I would recommend against using the "v0" mangling for exports, unless that is intended as more than just a "suggested" name mangling scheme, and the one to be adopted by rustc specifically. In lccc, to avoid naming problems caused by trying to select from two naming schemes, I use (and extended) the itanium syntax (not consistent with legacy - the mangling scheme is designed to produce consistent symbol names). The fact `#[export_name]`/`#[linkage_name]`/whatever it's called exists, though, means this isn't a non-starter without forcing the name mangling scheme upon all implementations. I would suggest using unmangled names, though. Knowing the constructons for itanium names, I can tell you that remembering `__rust_alloc` is a lot easier than `_RNvNtC4rust5alloc5alloc`, or `_ZN4rust5alloc5allocEmm`

> [@bjorn3](#):
>
> C/C++ allow directly calling the global allocator from other languages using malloc and freeC/C++ allow directly calling the global allocator from other languages using malloc and freeectly calling the global allocator from other languages using `malloc` and `free`

Note that the C++ global allocator is not the same as `malloc` or `free`, and the name is not accessible to other languages (On itanium x86\_64-Sys-V the basic allocator function is `_Znwm` (`::operator new(unsigned long)`). This is true of C, however.

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [July 28, 2021, 3:09pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/5 "2021-07-28T15:09:54Z")

</div>

I would love to see these functions made available, but I definitely don't think we should export the mangled names. Perhaps one day we might add native support for the mangling convention to C and C++ compilers, but until then, I think we should give these symbols clearer names.

We also need to define, stably, the precise semantics and non-semantics of these functions. For instance, some C code might expect the realloc function to act like C realloc, where passing NULL as the previous pointer makes it act like malloc, and passing 0 as the new size makes it act like free. (Those semantics make C realloc alone capable of providing the full allocation API with a single function pointer.) If we _don't_ want to provide those semantics, we should clearly document that, because that may surprise C developers. We'll already need to provide wrappers to export; we should consider providing those semantics for the realloc wrapper.

---

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [July 28, 2021, 3:22pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/6 "2021-07-28T15:22:51Z")

</div>

> [@josh](#):
>
> I would love to see these functions made available, but I definitely don't think we should export the mangled names.

This was the idea of @eddyb. The reasoning behind it is that it gives nice backtraces and that it is distinctively a Rust symbol and not a C or mangled C++ symbol AFAIK. [https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/upstreaming.20LLVM.20patch.20for.20\_\_rust\_.20alloc.20functions/near/247438729](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/upstreaming.20LLVM.20patch.20for.20__rust_.20alloc.20functions/near/247438729)

I am fine either way though. What do you think would be a good prefix? `__rust_` is currently used for unstable internal interfaces, so I think either these allocator functions should use a different prefix or the internal interfaces should use a different prefix to prevent confusion about what is an implementation detail and what is stable.

> [@josh](#):
>
> We also need to define, stably, the precise semantics and non-semantics of these functions.

The semantics are identical to the corresponding methods of the `GlobalAlloc` trait. These functions directly call the methods on `#[global_allocator]` with only an extra `Layout::from_size_align` call to assemble a `Layout` from the size and align arguments as `Layout` is not FFI-safe.

> [@bjorn3](#):
>
> These functions directly correspond to the respective methods on `GlobalAlloc` . All functions have the same safety invariants as the corresponding methods on `GlobalAlloc` . In addition the safety invariants of `Layout::from_size_align` must be followed when called with the given `size` and `align` .

From the safety section of `GlobalAlloc::realloc`:

> # [Safety](https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#safety-4)
> 
> This function is unsafe because undefined behavior can result if the caller does not ensure all of the following:
> 
> - `ptr` must be currently allocated via this allocator,

This means that `realloc` can't be used in the place of `malloc`.

> - `layout` must be the same layout that was used to allocate that block of memory,
> - `new_size` must be greater than zero.

This means that `realloc` can't be used in the place of `free`.

> - `new_size` , when rounded up to the nearest multiple of `layout.align()` , must not overflow (i.e., the rounded value must be less than `usize::MAX` ).
> 
> (Extension subtraits might provide more specific bounds on behavior, e.g., guarantee a sentinel address or a null pointer in response to a zero-size allocation request.)

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [July 28, 2021, 5:43pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/7 "2021-07-28T17:43:37Z")

</div>

I think either `rust_alloc` or `rustalloc_alloc` would be fine.

Regarding semantics, I'm _not_ suggesting we need to change the semantics of these functions. But if we're going to export C symbols whose suffixes are the same as well-known C functions (e.g. `realloc`), we should explicitly document cases in which they differ from the semantics of those C functions. For instance, something like this:

Note that unlike the C `realloc` function:

- `rust_realloc` only works on an existing memory allocation. Passing NULL to create a fresh allocation is not valid; call `rust_alloc` instead.
- `rust_realloc` does not accept a new size of 0. To free memory, call `rust_free` instead.

---

<div class="post-metadata">

### Author: ![InfernoDeity](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/infernodeity/32/7588_2.png) [@InfernoDeity](https://internals.rust-lang.org/u/InfernoDeity)
#### Post date: [July 28, 2021, 6:25pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/8 "2021-07-28T18:25:45Z")

</div>

There are also significant signature differences, in that each function takes an alignment, so those would have to be documented.

Speaking of signature differences, the signature in C/++ should use `uinptr_t` in place of `size_t`. They are not always the same, and `usize` is going to be equivalent to `uintptr_t` if they are different.

---

<div class="post-metadata">

### Author: ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)
#### Post date: [July 29, 2021, 10:55am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/9 "2021-07-29T10:55:36Z")

</div>

> [@InfernoDeity](#):
>
> I would recommend against using the "v0" mangling for exports, unless that is intended as more than just a "suggested" name mangling scheme, and the one to be adopted by rustc specifically.

I don't understand what this is referring to. `v0` is the first version of the _specified_ Rust mangling scheme, and while some progress was stalled by having to upstream it into tools like debuggers, the plan was all along to make it the default. We might be able to do that soon, once [it fully supports unstable const generics](https://github.com/rust-lang/rust/pull/87194).

Anyway, alternative implementations of Rust don't need produce the same symbols, and something like `_RNvNtC4rust5alloc5alloc` is not obtainable through mangling, it just _happens to_ fit the syntax and be supported by `rustc-demangle` and (in recent/future versions) debuggers.

It would always be used through `#[export_name = "..."]`/`#[link_name = "..."]` and specified as an opaque string as far as an RFC like this would be concerned.

> [@InfernoDeity](#):
>
> Knowing the constructons for itanium names, I can tell you that remembering `__rust_alloc` is a lot easier than `_RNvNtC4rust5alloc5alloc` , or `_ZN4rust5alloc5allocEmm`

Why would you remember it? It's an opaque identifier that is meant to be copy-pasted from the RFC (or Rust docs, if it ends up somewhere in e.g. `alloc` docs).

> [@josh](#):
>
> I would love to see these functions made available, but I definitely don't think we should export the mangled names. Perhaps one day we might add native support for the mangling convention to C and C++ compilers, but until then, I think we should give these symbols clearer names.

Why would Rust mangling support ever exist in a non-Rust compiler? Why would it make sense? It's not like you can have mangled symbols you can name externally, for most things - that ability would kneecap the sound isolation of symbols from different crates that may share e.g. a name (or even a version), but are considered separate by Cargo.

A name like `rust_alloc` could easily be defined in C code, without arising any kind of suspicion, and even completely accidentally. We can add more qualifiers in there like `rust_internals_global_allocator_alloc`, to make it more visually distinct, but at the end of the day, a symbol that matches the Rust (v0) mangling scheme and does not fit any C or C++ naming conventions, is IMO superior for distinguishing it.

* * *

My _personal_ opinion wrt this RFC, ignoring the choice of names, is that we shouldn't expose the Rust global allocator like this, even if there is a stable API on the Rust side.

There may be unknown unknowns, and while on the Rust side we can account for some of them (e.g. needing more of these internal entry-points into the global allocator, or needing to pass more information through one of the entry-points) by reshuffling the internal codegen, we more or less lose that ability once there's any exposure to C.

> [@bjorn3](#):
>
> This RFC can be implemented by renaming the methods of the allocator shim and then adding documentation that the signatures of the functions in the allocator shim must not change.

Alternatively, if people _really_ want some stable C API for the Rust global allocator, and if we don't want to let C have the ability to override it at all, we could instead "just" add a few `#[no_mangle]`/`#[export_name = "..."]` functions to the `alloc` crate, that do what everyone can already do in their own FFI crate.

That I could get behind, and I probably wouldn't care ~~too~~ as much about the choices of symbol names.

---

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [July 29, 2021, 11:58am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/10 "2021-07-29T11:58:56Z")

</div>

> [@eddyb](#):
>
> Alternatively, if people _really_ want some stable C API for the Rust global allocator, and if we don't want to let C have the ability to override it at all, we could instead "just" add a few `#[no_mangle]` / `#[export_name = "..."]` functions to the `alloc` crate, that do what everyone can already do in their own FFI crate.

C can't override it anyway as rust will refuse to compile a `dylib`, `cdylib`, `staticlib` or `bin` unless a global allocator is defined on the rust side. While symbol interposition would be possible at runtime, this can be prevented by using the "protected" visibility for the symbols: [LLVM Language Reference Manual — LLVM 18.0.0git documentation](https://llvm.org/docs/LangRef.html#visibility-styles)

> [@eddyb](#):
>
> There may be unknown unknowns, and while on the Rust side we can account for some of them (e.g. needing more of these internal entry-points into the global allocator, or needing to pass more information through one of the entry-points) by reshuffling the internal codegen, we more or less lose that ability once there's any exposure to C.

If we want to reshuffle the internal codegen, these functions could still be emitted as wrappers, just not used by `alloc::alloc::Global`.

---

<div class="post-metadata">

### Author: ![InfernoDeity](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/infernodeity/32/7588_2.png) [@InfernoDeity](https://internals.rust-lang.org/u/InfernoDeity)
#### Post date: [July 29, 2021, 11:59am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/11 "2021-07-29T11:59:17Z")

</div>

> [@eddyb](#):
>
> Why would you remember it? It's an opaque identifier that is meant to be copy-pasted from the RFC (or Rust docs, if it ends up somewhere in e.g. `alloc` docs).

Whenever I write code in anything, I typically memorize useful things. Having to copy-paste the name every time I want to use it would cost more time than just remembering it, but it's easier for an unmangled name to be remembered.

> [@eddyb](#):
>
> Anyway, alternative implementations of Rust don't need produce the same symbols, and something like `_RNvNtC4rust5alloc5alloc` is not obtainable through mangling

Isn't it, though? I don't know the rust-v0 mangling as well as Itanium, but that looks like the mangling of `rust::alloc::alloc`.

> [@eddyb](#):
>
> It's not like you can have mangled symbols you can name externally, for most things - that ability would kneecap the sound isolation of symbols from different crates that may share e.g. a name

If you only have one copy of a crate in a dependency graph, they could be reduced to their own names, and of course, special crates like `std`/`alloc`/`core` can get priority over their exact name.

> [@eddyb](#):
>
> There may be unknown unknowns, and while on the Rust side we can account for some of them (e.g. needing more of these internal entry-points into the global allocator, or needing to pass more information through one of the entry-points) by reshuffling the internal codegen, we more or less lose that ability once there's any exposure to C.

Aren't the C exports just thin wrappers arround the counterparts in `alloc::alloc`? If so, I highly doubt the signatures of those need to change, given that it's effectively calling a function with a stable definition.

---

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [July 29, 2021, 12:06pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/12 "2021-07-29T12:06:18Z")

</div>

> [@InfernoDeity](#):
>
> Isn't it, though? I don't know the rust-v0 mangling as well as Itanium, but that looks like the mangling of `rust::alloc::alloc` .

`_RNvNtC4rust5alloc5alloc` demangles to `rust[0]::alloc::alloc`. It has a 0 as crate disambiguator, which is extremely unlikely to happen (1 in 2^64 times). Rustc would produce something like `_RNvNtCsiHrIwmIS61w_4rust5alloc5alloc` which demangles to `rust[d9d1be2d9a8a11c8]::alloc::alloc` depending on the `-Cmetadata` arguments given (and possibly in the future rustc version).

You can verify this using `rustc_demangle`: [Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fa815a25bf1fa1db65fecc0b9ce4603e)

---

<div class="post-metadata">

### Author: ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)
#### Post date: [July 30, 2021, 11:36am UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/13 "2021-07-30T11:36:32Z")

</div>

> [@InfernoDeity](#):
>
> I don't know the rust-v0 mangling as well as Itanium, but that looks like the mangling of `rust::alloc::alloc` .

It is, but there's no disambiguator set for the `rust` "crate", which, as @bjorn3 also mentioned, is not something that normally happens (if we do use this kind of "artificial mangling", we should make sure that a disambiguator of `0` cannot actually exist in other situations, by making `rustc` error if it happens to arise from hashing, regardless how extremely unlikely that may be).

> [@InfernoDeity](#):
>
> If you only have one copy of a crate in a dependency graph, they could be reduced to their own names, and of course, special crates like `std` / `alloc` / `core` can get priority over their exact name.

Perhaps, but without whole-program compilation and/or Cargo informing `rustc` that any one crate in the graph is somehow "uniquely named", the only sound thing to do is to always include the crate disambiguators (and ensure that they're unique across the dependency graph).

> [@InfernoDeity](#):
>
> Aren't the C exports just thin wrappers arround the counterparts in `alloc::alloc` ? If so, I highly doubt the signatures of those need to change, given that it's effectively calling a function with a stable definition.

Right now, the functions @bjorn3 was talking about are the exact mechanism through which `#[global_allocator]` (or the default one in `std`) is injected into any crate using `alloc` - i.e. `alloc` imports and calls undefined symbols, that get defined in a downstream crate (by the compiler).

So by exposing them directly, there's a risk of them being (accidentally) (ab)used to hijack the Rust global allocator (but see the "alias" suggestion below, that could solve this neatly).

> [@bjorn3](#):
>
> While symbol interposition would be possible at runtime, this can be prevented by using the "protected" visibility for the symbols: [LLVM Language Reference Manual — LLVM 13 documentation](https://llvm.org/docs/LangRef.html#visibility-styles)

Ah that'd be handy, can you open an issue about using it for weak lang items and whatnot? Though for anything we use real mangling for, the crate disambiguators are going to make (accidental) external interference unlikely/impractical.

> [@bjorn3](#):
>
> If we want to reshuffle the internal codegen, these functions could still be emitted as wrappers, just not used by `alloc::alloc::Global` .

Fair enough, that's a good point, and combined with the difficulty of overriding the definitions from C (assuming the link order prevents it today), I'm less concerned.

* * *

Perhaps we could have an "alias symbol" feature, say, an attribute like `#[export_name = "..."]`, but which instead of setting the symbol name of the function, produces a [LLVM alias](https://llvm.org/docs/LangRef.html#aliases) (similar to ones LLVM generates from merge-functions), which should be as efficient to call as the original function, but is separate for the purposes of late-binding/overriding.

Even if we don't expose it to the language, the alloc entry-points are special enough that we could at least hardcode this behavior for them in particuler.

---

<div class="post-metadata">

### Author: ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)
#### Post date: [July 30, 2021, 5:37pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/14 "2021-07-30T17:37:37Z")

</div>

> [@eddyb](#):
>
> So by exposing them directly, there's a risk of them being (accidentally) (ab)used to hijack the Rust global allocator (but see the "alias" suggestion below, that could solve this neatly).

I have updated the RFC to clarify that this is not allowed. I agree that it is best to prevent this completely though.

---

<div class="post-metadata">

### Author: ![ojeda](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ojeda/32/6139_2.png) [@ojeda](https://internals.rust-lang.org/u/ojeda)
#### Post date: [July 31, 2021, 12:12pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/15 "2021-07-31T12:12:45Z")

</div>

> [@josh](#):
>
> For instance, some C code might expect the realloc function to act like C realloc, where passing NULL as the previous pointer makes it act like malloc, and passing 0 as the new size makes it act like free. (Those semantics make C realloc alone capable of providing the full allocation API with a single function pointer.) If we _don't_ want to provide those semantics, we should clearly document that, because that may surprise C developers.

Side-note: `realloc()` for `size == 0` is best avoided due to differing behaviors. It is obsolescent and will be UB soon.

---

<div class="post-metadata">

### Author: ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)
#### Post date: [October 29, 2021, 12:13pm UTC](https://internals.rust-lang.org/t/pre-rfc-support-using-the-rust-allocator-from-c/15097/16 "2021-10-29T12:13:31Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
