转换产生无效指针的函数引用?

Mac*_*cki 9 types casting undefined-behavior rust

我正在跟踪第三方代码中的错误,并将其缩小到类似的范围。

use libc::c_void;

pub unsafe fn foo() {}

fn main() {
    let ptr = &foo as *const _ as *const c_void;
    println!("{:x}", ptr as usize);
}
Run Code Online (Sandbox Code Playgroud)

在稳定的1.38.0上运行,这会打印功能指针,但beta(1.39.0-beta.6)和夜间返回'1'。(游乐场

_推断出什么,为什么行为发生了变化?

我认为正确的方法只是foo as *const c_void,但这不是我的代码。

Sve*_*ach 3

此答案基于对此问题引发的错误报告的回复答复。

\n\n

Rust 中的每个函数都有其单独的函数项类型,该类型与每个其他函数的函数项类型不同。因此,函数项类型的实例根本不需要存储任何信息 \xe2\x80\x93 从其类型中可以清楚地看出它指向什么函数。所以变量x在

\n\n
let x = foo;\n
Run Code Online (Sandbox Code Playgroud)\n\n

是一个大小为 0 的变量。

\n\n

函数项类型隐式强制为函数指针类型必要时,变量

\n\n
let x: fn() = foo;\n
Run Code Online (Sandbox Code Playgroud)\n\n

是一个指向任何具有签名的函数的通用指针fn(),因此需要存储一个指向它实际指向的函数的指针,因此x就是指针的大小。

\n\n

如果您获取函数的地址 ,&foo您实际上获取的是零大小的临时值的地址。在此提交到rustrepo之前,零大小的临时对象用于在堆栈上创建分配,并&foo返回该分配的地址。自此提交以来,零大小类型不再创建分配,而是使用魔术地址 1。这解释了 Rust 不同版本之间的差异。

\n