幻像成员会使我的结构具有固定的内存地址吗?

发布于 2025-01-18 05:34:16 字数 584 浏览 3 评论 0原文

我正在编写与 C API 通信的 Rust 代码,并且我需要某个结构来拥有固定的内存地址。到目前为止,我发现:

如果我理解正确的话,PhantomPinned 将是最容易使用的:只需将其作为成员即可使我的结构自动具有固定的内存地址。这是正确的吗?

I'm writing Rust code which communicates with a C API, and I need a certain struct to have a fixed memory address. So far, I found:

If I understood correctly, PhantomPinned would be the easiest to use: just having it as a member would make my struct automatically have a fixed memory address. Is this correct?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

╭⌒浅淡时光〆 2025-01-25 05:34:16

您需要的是Pin。它是一个防止对象移动的指针。

pin_mut!() 只是一个宏,可帮助您创建一个 Pin 实例,而无需堆分配或不安全代码。

PhantomPinned 还有另一个相关的目标。默认情况下,您的类型将实现 Unpin特征(除非它包含不实现 Unpin 的类型,但大多数类型都实现)。这是有问题的,因为对于实现 Unpin 的类型,Pin 没有效果:它不会阻止您移动它们。这是因为大多数类型不需要固定的内存地址。想想 i32,例如:即使您创建了 Pin<&mut i32>,您也可以移动它,因为 i32 实现了 取消固定,因为即使您移动它也不会发生任何不良情况,并且不会验证任何数据。

因此,为了使Pin有效,您需要取消实现Unpin。这是通过包含一个不将 Unpin 本身实现为字段的字段,或者具有一个负 impl 来完成的(请参阅 什么是 Rust 中的自动特征?):

impl !Unpin for MyType {}

不幸的是,负 impls 不稳定。相反,标准库提供了 PhantomPinned 类型,这是无成本的(ZST),但没有实现 Unpin (它有一个负面的隐含,因为标准库是允许使用不稳定的功能它可以做到这一点)。现在,当您的类型包含它时,它也会变成 !Unpin

总而言之,您需要在结构中包含 PhantomPinned,这样它就不会被 Unpin,并且您需要将其包装在 Pin 中,这样它就可以将无法移动。

What you need is Pin. It's a pointer that keeps your object from being moved.

pin_mut!() is just a macro that helps you create a Pin instance without heap allocation or unsafe code.

PhantomPinned has another, though related, goal. By default, your type will implement the Unpin trait (unless it contains a type that don't implement Unpin, however most types do). This is problematic, because for types that implements Unpin, Pin has no effect: it does not prevent you from moving them. This is because most types do not need a fixed memory address. Think about i32, for example: even if you create Pin<&mut i32>, you can move it, because i32 implements Unpin, because even if you'll move it nothing bad will happen, and no data will be validated.

So for Pin to be effective you need to un-impl Unpin. This is done by either including a field that doesn't implements Unpin itself as a field, or having a negative impl (see What is an auto trait in Rust?):

impl !Unpin for MyType {}

Unfortunately, negative impls are unstable. Instead, the standard library provides the PhantomPinned type, which is costless (a ZST), but doesn't implement Unpin (it has a negative impl, since the standard library is allowed to use unstable features it can do that). And now when your type includes it it becomes !Unpin too.

To sum up, you need to include PhantomPinned in your struct so it will not be Unpin, and you need to wrap it in Pin so it will be unmovable.

听闻余生 2025-01-25 05:34:16

Rust中唯一的不容易变化的值是pin&lt; t&gt;中的值,并且仅当t不实现unpin时。

t可能是参考或某些智能指针类型,例如box arc ,但pin> pin以指定该指定。该值可能不会移动。

undin是针对不在乎他们是否被固定的类型实现的特征。这是一个标记性状自动针对所有类型的成员实现unpin的类型。 phantompinned是一种简单的零大小类型实施UNVIN

请注意,unvin仅与pin> pin包装值 - PIN> PIN之外的值仍然可以移动。需要不移动该值的操作应采用pin&lt;&amp; mut t&gt;而不是&amp; mut t

pin_mut是将堆栈值转换为固定指针的宏。对于已知安全案例来说,这只是一个方便,并没有真正涉及PIN的工作方式。


因此,对于您的情况,听起来您的结构应该具有phantompined成员,并且其所有操作都应采用PIN包装参考。

The only unmoveable value in Rust is the value in Pin<T> and only if T does not implement Unpin.

T may be a reference or some smart pointer type like Box or Arc, but Pin is needed to specify that the value may not move.

Unpin is a trait implemented for types that don't care if they are moved, even if they are pinned. It's a marker trait automatically implemented for all types whose members all implement Unpin. PhantomPinned is a simple, zero sized type that does not implement Unpin, so it may be added to a struct or enum to make it not automatically implement Unpin.

Note that Unpin is only relevant to Pin wrapped values - values outside of Pin can still be moved. Operations requiring the value not be moved should take a Pin<&mut T> instead of &mut T.

pin_mut is a macro for converting a stack value to a pinned pointer. It's just a convenience for a known-safe case and doesn't really play into how Pin works.


So for your case, it sounds like your structure should have a PhantomPinned member, and all of its operations should take a pin-wrapped reference.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文