Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

应用二进制接口(ABI)

本节记录了影响 crate 编译输出 ABI 的特性。

有关指定导出函数 ABI 的信息,请参阅 外部函数。有关指定链接外部库 ABI 的信息,请参阅 外部块

used属性

used 属性 只能应用于 static。此 属性 强制编译器在输出的目标文件(.o、.rlib 等,不包括最终的可执行文件)中保留变量,即使该变量未被 crate 中的任何其他项使用或引用。然而,链接器仍然可以自由地删除这样的项。

下面是一个示例,展示了编译器在什么条件下会将 static 项保留在输出的目标文件中。

#![allow(unused)]
fn main() {
// foo.rs

// 即使未使用,也因为 #[used] 而被保留:
#[used]
static FOO: u32 = 0;

// 因为未使用而可以被删除:
#[allow(dead_code)]
static BAR: u32 = 0;

// 因为是公共可达的而被保留:
pub static BAZ: u32 = 0;

// 因为被一个公共可达的函数引用而被保留:
static QUUX: u32 = 0;

pub fn quux() -> &'static u32 {
    &QUUX
}

// 因为被一个私有的、未使用的(死代码)函数引用而可以被删除:
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 版次差异

在 2024 版次 之前,允许不带 unsafe 限定地使用 no_mangle 属性。

link_section 属性 指定了 函数static 内容将放置在目标文件的哪个节中。

link_section 属性使用 MetaNameValueStr 语法来指定节的名称。

#![allow(unused)]
fn main() {
#[unsafe(no_mangle)]
#[unsafe(link_section = ".example_section")]
pub static VAR1: u32 = 1;
}

此属性是不安全的,因为它允许用户将数据和代码放置在不期望它们的内存节中,例如将可变数据放置在只读区域中。

2024 版次差异

在 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() { }
}

此属性是不安全的,因为具有自定义名称的符号可能会与另一个具有相同名称的符号(或与众所周知的符号)发生冲突,从而导致未定义行为。

2024 版次差异

在 2024 版次 之前,允许不带 unsafe 限定地使用 export_name 属性。