types - 转换产生无效指针的函数引用?
问题描述
我正在追踪第三方代码中的一个错误,并将其缩小到类似的范围内。
use libc::c_void;
pub unsafe fn foo() {}
fn main() {
let ptr = &foo as *const _ as *const c_void;
println!("{:x}", ptr as usize);
}
在稳定的 1.38.0 上运行,这会打印函数指针,但 beta (1.39.0-beta.6) 并每晚返回“1”。(游乐场)
推断是什么_
以及为什么行为发生了变化?
我认为正确的转换方法是foo as *const c_void
,但这不是我的代码。
解决方案
此答案基于对此问题所激发的错误报告的回复。
Rust 中的每个函数都有其单独的函数项类型,这与其他所有函数的函数项类型不同。出于这个原因,函数项类型的实例根本不需要存储任何信息——它所指向的函数从它的类型中可以清楚地看出。所以变量 x 在
let x = foo;
是大小为 0 的变量。
函数项类型在必要时隐式强制转换为函数指针类型。变量
let x: fn() = foo;
是指向任何带有签名的函数的通用指针fn()
,因此需要存储指向它实际指向的函数的指针,因此 的大小x
是指针的大小。
如果你获取一个函数的地址&foo
,你实际上是在获取一个零大小的临时值的地址。在提交到rust
repo之前,零大小的临时对象用于在堆栈上创建分配,并&foo
返回该分配的地址。自此提交以来,零大小类型不再创建分配,而是使用魔术地址 1。这解释了不同版本的 Rust 之间的差异。
推荐阅读
- wordpress - 有什么方法可以在我的 WordPress 网站上显示 WooCommerce 迷你购物车?
- javascript - 将选项值转换为链接 - Javascript
- python - 即使 gzip 压缩的文件相同,Python 2.7 filecmp.cmp 也会返回 false
- python - 将应用程序窗口设为最顶层(活动)窗口
- macos - Mac OSX Server - 应用到附件功能
- sql-server - RDS 实例存储已满
- delphi - 在新记录中自动获取 customer_id
- javascript - 使用 jquery 为输入字段设置值未设置为输入字段的模型
- memory - 一个内存地址通常保存多少字节?
- java - Nodejs:Spawn jar(不可执行)