应用程序二进制接口(ABI)
本节记录了影响 crate 编译输出的 ABI 的特性。
相关信息请参阅 extern 函数 以了解如何指定导出函数的 ABI,参阅 外部块 以了解如何指定链接外部库的 ABI。
used 属性
used 属性 强制将一个 static 保留在输出目标文件(.o、.rlib 等,但不包括最终二进制文件)中,即使它在 crate 中从未被其他程序项使用或引用。不过,链接器仍然可以自由地移除它。
Example
#![allow(unused)] fn main() { // lib.rs // 因为有 `#[used]`,此静态项被保留。 #[used] static S1: u8 = 0; // 因为未使用,此静态项可被移除。 #[allow(dead_code)] static S2: u8 = 0; // 因为可被公开访问,此静态项被保留。 pub static S3: u8 = 0; // 因为被一个可公开访问的函数引用,此静态项被保留。 static S4: u8 = 0; #[unsafe(no_mangle)] pub fn f4() -> &'static u8 { &S4 } // 因为只被一个私有的、未使用的(死)函数引用,此静态项可被移除。 static S5: u8 = 0; #[allow(dead_code)] fn f5() -> &'static u8 { &S5 } }$ rustc -O --emit=obj --crate-type=rlib lib.rs $ LC_ALL=C nm -C lib.o 0000000000000000 R lib::S1 0000000000000000 R lib::S3 0000000000000000 r lib::S4 0000000000000000 T f4
used 属性使用 MetaWord 语法。
used 属性只能应用于 static 程序项。
只有程序项上的第一次 used 使用才有效。
Note
rustc会对第一次之后的任何使用给出 lint 警告。
no_mangle 属性
no_mangle 属性可用于任何程序项,以禁用在符号名称上应用标准的名称修饰。该程序项的符号将是该程序项名称的标识符。
此外,该程序项将从生成的库或目标文件中公开导出,类似于 used 属性。
此属性是不安全的,因为未修饰的符号可能与另一个同名符号(或已知符号)冲突,导致未定义行为。
#![allow(unused)]
fn main() {
#[unsafe(no_mangle)]
extern "C" fn foo() {}
}
2024 Edition differences
在 2024 版之前,允许在不使用
unsafe限定的情况下使用no_mangle属性。
link_section 属性
link_section 属性指定将函数或 static 的内容放入目标文件的哪个节中。
link_section 属性使用 MetaNameValueStr 语法来指定节名称。
#![allow(unused)]
fn main() {
#[cfg(target_os = "linux")] {
#[unsafe(no_mangle)]
#[unsafe(link_section = ".example_section")]
pub static VAR1: u32 = 1;
}
}
此属性是不安全的,因为它允许用户将数据和代码放入未预期它们的内存节中,例如将可变数据放入只读区域。
只有程序项上的第一次 link_section 使用才有效。
Note
rustc会对第一次之后的任何使用给出未来兼容性警告。这在未来可能成为错误。
2024 Edition differences
在 2024 版之前,允许在不使用
unsafe限定的情况下使用link_section属性。
export_name 属性
export_name 属性指定将在函数或 static 上导出的符号名称。
export_name 属性使用 MetaNameValueStr 语法来指定符号名称。
#![allow(unused)]
fn main() {
#[unsafe(export_name = "exported_symbol_name")]
pub fn name_in_rust() { }
}
此属性是不安全的,因为具有自定义名称的符号可能与另一个同名符号(或已知符号)冲突,导致未定义行为。
只有程序项上的第一次 export_name 使用才有效。
Note
rustc会对第一次之后的任何使用给出未来兼容性警告。这在未来可能成为错误。
2024 Edition differences
在 2024 版之前,允许在不使用
unsafe限定的情况下使用export_name属性。