Rust编程中Pin和Unpin的用法

文章目录

    • Pin
      • Pin的作用
      • Pin的基本限制
      • Pin定义及用法
    • Unpin
    • Pin和Unpin的注意事项
    • 实际开发中的建议

在Rust编程语言中Pin和Unpin是与内存安全和异步编程相关的概念。它们的主要目的是确保某些类型在内存中的位置不变,尤其是在处理指针和异步操作时。Pin用于确保一个值在内存中的位置不变,从而避免因移动而引起的未定义行为。Unpin是个标记trait表示一个类型可以安全地移动,而不需要担心内存地址变化。在实际应用中,Pin和Unpin常被结合使用尤其是在涉及到异步编程和自引用数据结构时。

Pin

Pin是一个智能指针,用于确保数据在移动后不会被错误地移动。它主要用于需要保持在某个位置的类型,比如实现了异步特性的类型。

Pin的作用

1.防止数据在内存中移动
Pin类型包裹的数据通常不能通过常规方式移动。移动意味着改变内存地址,这可能破坏依赖地址稳定性的逻辑。

2.确保数据的地址稳定性
使用Pin时,编译器会保证无法在不经过安全验证的情况下移动被包裹的对象。

Pin的基本限制

1.不可变借用和操作受限
如果一个值被Pin包裹,你不能通过Pin<&T>来移动它或改变它的存储地址。如果需要修改值内容,可以通过Pin<&mut T>。

2.需要遵守Pin的操作规则
如果类型没有实现Unpin,数据就无法通过常规方式被移动或解包,必须通过安全的方式操作。

Pin定义及用法

pub struct Pin<P>(pub P);

当你将一个值放入Pin中时,Rust会禁止直接移动这个值,从而保证它在内存中的地址保持不变。这在处理某些需要固定位置的数据时非常重要。
在Rust中,堆上的数据可以通过Box、Vec等容器移动,而栈上的数据可以通过赋值或函数调用被移动。自引用类型依赖于特定的内存地址比如:

struct SelfReferencing {data: String,reference: *const String,
}impl SelfReferencing {//SelfReferencing data 被移动,其内部的reference会变成悬空指针(指向旧的内存地址)fn new(data: String) -> Self {//as *const String 用于将一种类型转换为另一种兼容的类型。//*const String 是一个原始指针类型,表示一个不可变的、无所有权的指针,指向一个String类型的值。//*const T: 指向T的不可变指针。 *mut T:指向 T 的可变指针。let reference = &data as *const String;Self { data, reference }}
}

使用Pin固定某个变量的内存地址,防止由于内存地址变化引发的错误。对应的调用如下所示:

use std::pin::Pin;fn main() {let data = String::from("Hello");let mut pinned_data = Pin::new(&data);// pinned_data 是固定的,不可被移动。
}

Pin的使用场景分析
1.异步编程中Pin确保异步任务中的数据不会被移动,从而保证Future的正确性。
2.自引用结构中避免因为数据移动导致悬空指针。

Unpin

Unpin是一个标记trait,表示一种类型可以安全地在内存中移动。换句话说如果一个类型实现了Unpin那么即使将它放在Pin中,也没有必要担心它的内存地址会在未来变化。大多数标准库中的类型(如Box、Rc等)默认实现了Unpin。而某些类型如自引用结构体则不应实现Unpin,以确保它们在被固定后不会被移动。

//这是一个不安全的trait,意味着只有在认为一个类型是安全的情况下,程序员才应该手动实现Unpin
pub unsafe trait Unpin { }
use std::marker::Unpin;
use std::pin::Pin;struct MyStruct {value: i32,
}// MyStruct 默认实现了 Unpin
impl Unpin for MyStruct {}fn main() {let my_value = MyStruct { value: 42 };let pinned_value = Pin::new(&my_value);// 因为 MyStruct 实现了 Unpin,可以安全地移动// into_inner 是 Pin 提供的一个方法,用于取出其内部的数据。// 如果类型实现了Unpin,Pin 中的数据就可以安全地移动。let moved_value = pinned_value.into_inner();
}

Pin和Unpin的注意事项

1.避免破坏Pin的语义
即使使用unsafe也不要随意移动被Pin包裹的!Unpin类型。不正确地操作可能导致未定义行为,例如悬垂指针(dangling pointer)或内存安全问题。

2.手动实现Unpin时的规则
只有在确定数据内部没有地址依赖时才能手动实现Unpin。如果存在复杂的内部引用关系,避免手动实现Unpin。

3.从Pin提取值
如果类型实现了Unpin,可以直接通过into_inner提取值。如果类型未实现Unpin,需要通过提供安全API或unsafe代码提取。

4.不要忽视Pin的限制
Pin旨在保护!Unpin类型的安全性,绕过这些限制可能会破坏数据一致性。

实际开发中的建议

1.避免滥用Pin
如果类型不需要地址稳定性,不需要使用Pin。过度使用Pin会让代码难以理解和维护。

2.对Unpin类型的Pin没有真正保护意义
如果类型实现了Unpin,Pin的保护作用基本没有意义。

3.手动实现Unpin时需谨慎
只有完全了解类型行为时才实现Unpin。确保在类型移动后,不会引发内存安全问题。

4.尽量使用高层API
在封装类型时,尽量通过安全封装和抽象避免直接使用unsafe操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/35381.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

threejs相机辅助对象cameraHelper

为指定相机创建一个辅助对象&#xff0c;显示这个相机的视锥。 想要在场景里面显示相机的视锥&#xff0c;需要创建两个相机。 举个例子&#xff0c;场景中有个相机A&#xff0c;想要显示相机A的视锥&#xff0c;那么需要一个相机B&#xff0c;把B放在A的后面&#xff0c;两个…

财务规划的变革:如何推动数据科学的转型和分析

在快速发展的金融世界中&#xff0c;财务专业人士越来越需要超越传统预算方式的数据分析方法&#xff0c;将现代化的预算技术、工具和方法引入到我们的企业发展过程中&#xff0c;并在企业内部发挥更具战略性的作用。数据科学、财务预测和预算分析是企业财务领域成功所必需的核…

PyTorch环境迁移指南

在进行深度学习研究和开发时,我们经常需要在不同计算机之间迁移PyTorch环境。无论是更换新设备还是在多台机器间协同工作,都需要确保环境配置的一致性。本文将详细介绍PyTorch环境迁移的完整流程和注意事项。 环境迁移看似简单,实则暗藏玄机。直接复制文件可能会遇到系统差异带…

深信服ATRUST与锐捷交换机端口链路聚合的配置

深信服ATRUST业务口原来只配置使用一个电口&#xff0c;近期出现流量达到800-900M接近端口的极限带宽。由于设备没有万光口&#xff0c;于是只好用2个光口来配置链接聚合。 下需附上深信服ATRST端口配置的截图&#xff0c;由于深信服ATRUST与锐捷交换机端口只共同支持源mac目的…

WPS EXCEL 使用 WPS宏编辑器 写32位十六进制数据转换为浮点小数的公式。

新建EXCLE文件 另存为xlsm格式的文件 先打开WPS的开发工具中的宏编辑器 宏编辑器编译环境 在工作区添加函数并编译&#xff0c;如果有错误会有弹窗提示&#xff0c;如果没有错误则不会弹 函数名字 ”HEXTOFLOAT“ 可以自己修改。 function HEXTOFLOAT(hex) { // 将十六…

亚马逊云服务器Amazon EC2

一、什么是Amazon EC2&#xff1f; Amazon Elastic Compute Cloud (Amazon EC2) 在 Amazon Web Services (AWS) 云中提供按需、可扩展的计算容量。使用 Amazon EC2 可降低硬件成本&#xff0c;让您能够更快地开发和部署应用程序。您可以使用 Amazon EC2 启动任意数量的虚拟服务…

1688:开启跨境电商新篇章

引言 在全球化贸易不断深化的今天&#xff0c;跨境电商已成为中小企业拓展国际市场的重要渠道。1688&#xff0c;作为阿里巴巴集团旗下领先的内贸平台&#xff0c;近年来也逐渐发力跨境电商领域&#xff0c;为全球买家提供了一个直通中国工厂的贸易平台。本文将带您深入了解16…

ES使用script进行复杂排序

es数据字段&#xff0c;关注_source内容&#xff0c;为自定义的es表字段内容 {"clerk_id": 3150036230,"clerk_follow_status": 60,"create_time": 1729156110000,"channel": 1,"mid": 1538020071,"binlog_timestamp&…

Leecode刷题C语言之可以被进一步捕获的棋子数

执行结果:通过 执行用时和内存消耗如下&#xff1a; 代码如下&#xff1a; int numRookCaptures(char** board, int boardSize, int* boardColSize) {int cnt 0, st 0, ed 0;int dx[4] {0, 1, 0, -1};int dy[4] {1, 0, -1, 0};for (int i 0; i < 8; i) {for (int j…

攻防世界杂项刷题笔记(引导模式)13-23

引言&#xff1a;14包括提取文件和流量分析&#xff0c;22很新颖&#xff01;&#xff01;其他的都是常规隐写 13.base64stego 经过上一次如来十三掌的磨练&#xff0c;这题在看到题干“十三掌”的时候我是丝毫不慌张的。附件给了压缩包&#xff0c;考虑是不是伪加密&#xf…

Linux-PWM应用编程

本章我们将学习如何对开发板上的 PWM 设备进行应用编程。 本章将会讨论如下主题内容。 ⚫ 应用层 PWM 编程介绍&#xff1b; ⚫ PWM 测试。 应用层如何操控 PWM 与 LED 设备一样&#xff0c;PWM 同样也是通过 sysfs 方式进行操控&#xff0c;进入到/sys/class/pwm 目录下&…

Seaborn | 绘制数据分布的两个函数distplot和countplot

distplot 和 countplot 是 seaborn&#xff08;Seaborn&#xff09;库中用于绘制数据分布的两个函数&#xff0c;它们各自有不同的用途和特点&#xff1a; 1. distplot&#xff08;分布图&#xff09; distplot 函数用于绘制单变量的分布图。它可以显示数据的直方图&#xff…

网络原理 网络协议栈

POSIX API与网络协议栈 unix有不同的衍生版本&#xff0c;针对不同的版本&#xff0c;通过Posix定义了一套标准的操作系统接口API&#xff0c;使得不同的开发版本可以使用相同的API调用&#xff0c;具有可移植性。 网络连接相关API&#xff1a; 客户端 socket() bind() con…

java注解(二):注解的解析以及应用场景、用注解和反射模拟junit框架代码演示

目录 1、什么是注解的解析&#xff1f; 2、解析注解的案例 1、自定义一个注解 2、在类和方法上使用自己定义的注解 3、解析注解 3、模拟Junit框架案例 1、自定义一个MyTest注解 2、定义一个测试类&#xff0c;使用自定义的注解 3、写一个启动类 本文章主要讲解什么是注…

【华科X地平线】DiffusionDrive:端到端截断扩散模型

论文: https://arxiv.org/pdf/2411.14499 代码: https://github.com/hustvl/DiffusionDrive 0. 摘要 最近&#xff0c;扩散模型作为一种强大的生成式技术&#xff0c;已经出现在机器人策略学习领域&#xff0c;能够建模多模态动作分布。利用其进行端到端自动驾驶的能力是一个…

HarmonyOS 5.0应用开发——Ability与Page数据传递

【高心星出品】 文章目录 Ability与Page数据传递Page向Ability传递数据Ability向Page传递数据 Ability与Page数据传递 基于当前的应用模型&#xff0c;可以通过以下几种方式来实现UIAbility组件与UI之间的数据同步。 使用EventHub进行数据通信&#xff1a;在基类Context中提供…

【unity框架开发10】从零手搓一个UI管理器/UI框架,自带一个提示界面,还有自带DOTween动画效果(2024/10/10修改补充)

最终效果 文章目录 最终效果前言UI组件和布局的基础使用UI管理器1、新增UI面板层枚举2、初始化2.1、用代码创建画布2.2、用代码创建UI面板的父物体层2.3、代码添加EventSystem物体 3、ShowPanel显示面板方法4、HidePanel隐藏面板的方法5、CloseUI关闭界面的方法6、UI界面基类 测…

智能指针【C++11】

文章目录 智能指针std::auto_ptr std::unique_ptrstd::shared_ptrstd::shared_ptr的线程安全问题std::weak_ptr 智能指针 std::auto_ptr 管理权转移 auto_ptr是C98中引入的智能指针&#xff0c;auto_ptr通过管理权转移的方式解决智能指针的拷贝问题&#xff0c;保证一个资源…

Win11 24h2 不能正常ensp

Win11 24h2 不能正常ensp 因为Win11 24h2的内核大小更改&#xff0c;目前virtualbox在7.1.4中更新解决了。而ensp不支持5.2.44之后的virtualbox并已停止维护&#xff0c;不再进行5.2.44修复&#xff0c;virtualbox 5.2.24的ntdll文件sizeofimage问题&#xff0c;此问题导致ens…

使用GO--Swagger生成文档

概述 在前后端分离的项目中&#xff0c;后端配置swagger可以很好的帮助前端人员了解后端接口参数和数据传输。go-swagger 是一个功能全面且高性能的Go语言实现工具包&#xff0c;用于处理Swagger 2.0&#xff08;即OpenAPI 2.0&#xff09;规范。它提供了丰富的工具集&#x…