应用程序二进制接口 (ABI)
本节介绍影响 crate 编译输出的 ABI 的特性。
有关指定导出函数的 ABI 的信息,请参阅 extern 函数。有关指定链接外部库的 ABI 的信息,请参阅 外部块。
used
属性
used
属性 只能应用于 static
项。即使变量在 crate 中的任何其他项中未使用或未被引用,此 属性 也会强制编译器将变量保留在输出对象文件(.o、.rlib 等,不包括最终二进制文件)中。但是,链接器仍然可以自由地删除此类项。
下面是一个示例,展示了在什么条件下编译器会将 static
项保留在输出对象文件中。
#![allow(unused)] fn main() { // foo.rs // This is kept because of `#[used]`: #[used] static FOO: u32 = 0; // This is removable because it is unused: #[allow(dead_code)] static BAR: u32 = 0; // This is kept because it is publicly reachable: pub static BAZ: u32 = 0; // This is kept because it is referenced by a public, reachable function: static QUUX: u32 = 0; pub fn quux() -> &'static u32 { &QUUX } // This is removable because it is referenced by a private, unused (dead) function: static CORGE: u32 = 0; #[allow(dead_code)] fn corge() -> &'static u32 { &CORGE } }
$ rustc -O --emit=obj --crate-type=rlib foo.rs
$ nm -C foo.o
0000000000000000 R foo::BAZ
0000000000000000 r foo::FOO
0000000000000000 R foo::QUUX
0000000000000000 T foo::quux
no_mangle
属性
no_mangle
属性 可以用于任何 项,以禁用标准符号名称修饰。该项的符号将是该项名称的标识符。
此外,该项将从生成的库或对象文件中公开导出,类似于 used
属性。
此属性是不安全的,因为未修饰的符号可能与另一个同名符号(或与一个众所周知的符号)冲突,从而导致未定义的行为。
#![allow(unused)] fn main() { #[unsafe(no_mangle)] extern "C" fn foo() {} }
版本差异:在 2024 版本之前,允许在没有
unsafe
限定符的情况下使用no_mangle
属性。
link_section
属性
link_section
属性 指定 函数 或 静态 内容将被放置到的对象文件的节。它使用 MetaNameValueStr 语法来指定节名称。
此属性是不安全的,因为它允许用户将数据和代码放置到不期望它们的内存节中,例如将可变数据放置到只读区域中。
#![allow(unused)] fn main() { #[unsafe(no_mangle)] #[unsafe(link_section = ".example_section")] pub static VAR1: u32 = 1; }
版本差异:在 2024 版本之前,允许在没有
unsafe
限定符的情况下使用link_section
属性。
export_name
属性
export_name
属性 指定将在 函数 或 静态 上导出的符号的名称。它使用 MetaNameValueStr 语法来指定符号名称。
此属性是不安全的,因为具有自定义名称的符号可能与另一个同名符号(或与一个众所周知的符号)冲突,从而导致未定义的行为。
#![allow(unused)] fn main() { #[unsafe(export_name = "exported_symbol_name")] pub fn name_in_rust() { } }
版本差异:在 2024 版本之前,允许在没有
unsafe
限定符的情况下使用export_name
属性。