应用二进制接口 (ABI)
本节介绍影响 crate 编译输出的 ABI 的特性。
关于指定导出函数 ABI 的信息,请参阅 外部函数。关于指定链接外部库 ABI 的信息,请参阅 外部块。
used 属性
used 属性只能应用于 static 项。这个 属性强制编译器将变量保留在输出对象文件(.o、.rlib 等,不包括最终二进制文件)中,即使该变量未被 crate 中的任何其他项使用或引用。然而,链接器仍然可以自由地移除此类项。
下面是一个示例,展示了编译器在何种条件下将 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 属性可用于任何 项,以禁用标准的符号名称修饰(mangling)。该项的符号将是该项名称的标识符。
此外,该项将从生成的库或对象文件中公开导出,类似于 used 属性。
此属性不安全,因为未修饰的符号可能与同名的另一个符号(或与一个周知符号)发生冲突,从而导致未定义行为。
#![allow(unused)] fn main() { #[unsafe(no_mangle)] extern "C" fn foo() {} }
版本差异:在 2024 版本之前,允许在不加
unsafe限定词的情况下使用no_mangle属性。
link_section 属性
link_section 属性指定了 函数或 static 的内容将放入的目标文件段(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 属性指定了 函数或 static 将导出的符号名称。它使用 MetaNameValueStr 语法来指定符号名称。
此属性不安全,因为具有自定义名称的符号可能与同名的另一个符号(或与一个周知符号)发生冲突,从而导致未定义行为。
#![allow(unused)] fn main() { #[unsafe(export_name = "exported_symbol_name")] pub fn name_in_rust() { } }
版本差异:在 2024 版本之前,允许在不加
unsafe限定词的情况下使用export_name属性。