我想为我的板条箱创建C FFI API,但尚不清楚强制转换指针的安全性。伪代码:
#[no_mangle]
extern "C" fn f(...) -> *mut c_void {
let t: Box<T> = ...;
let p = Box::into_raw(t);
p as *mut c_void
}
这可以按预期工作,但是它的安全性如何?在C或C ++中,有一个特殊的void *
指针,并且C ++标准声明可以安全地对其进行强制转换。 sizeof(void *)
可能不等于sizeof(T *)
,但是可以保证sizeof(void *)
> = sizeof(T *)
。
Rust呢?是否有关于指针std::mem::size_of
的保证或指针之间的安全转换?还是所有指针的实现大小都相等,等于usize
?
“通用”是指您可以转换X *
而不会丢失任何内容。我不在乎类型信息;我关心的是指向不同事物的指针的大小不同,例如16位天中的near
/ far
指针。
4.10说
将“ pointer to cv T”转换为“ pointer to cv void”的结果指向类型为T的对象所在的存储位置的起始位置,
不可能sizeof(void *) < sizeof(T *)
,因为那样就不可能拥有存储位置的真实地址。
答案 0 :(得分:4)
否。
Rust的原始指针(和引用)目前有两种形式:
use std::mem;
fn main() {
println!("{}", mem::size_of::<*const u8>()); // 8
println!("{}", mem::size_of::<*const [u8]>()); // 16
}
没有允许同时存储两者的类型。甚至mem::transmute
的大锤子也行不通:
use std::mem;
unsafe fn example(mut thin: *const u8, mut fat: *const [u8]) {
fat = mem::transmute(thin);
thin = mem::transmute(fat);
}
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> src/main.rs:4:11
|
4 | fat = mem::transmute(thin);
| ^^^^^^^^^^^^^^
|
= note: source type: `*const u8` (64 bits)
= note: target type: `*const [u8]` (128 bits)
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> src/main.rs:5:12
|
5 | thin = mem::transmute(fat);
| ^^^^^^^^^^^^^^
|
= note: source type: `*const [u8]` (128 bits)
= note: target type: `*const u8` (64 bits)
由于胖指针的布局是Rust特定的概念,因此绝不应通过FFI访问它们。这意味着只应使用细指针,所有细指针都具有统一的已知大小。
另请参阅: