Rust 学习笔记:修复所有权常见错误

Rust所有权规则误解?借用检查器的错误消息解读 Rust的借用检查器和所有权机制通过编译时静态分析确保内存安全。本文剖析了开发者常见误区:所有权转移误解(变量绑定非拷贝)、函数传参陷阱和复合类型部分移动问题,并给出clone()显式复制或引用传递的解决方案。详细解读了借用检查器的三类典型错误(E0506不可变借用修改冲突、E0499多重可变借用、E0106悬垂引用)及其修复策略,如缩短借用生命周期或使用RefCell内部可变性。同时介绍了生命周期标注的实用技巧和迭代场景的冲突处理方法。Rust的设计哲学强调所有权唯一性、借用独占性和生命周期有效性,在编译 阅读详情

Rust 学习笔记:修复所有权常见错误

错误一:返回栈上的引用

错误代码:

fn return_a_string() -> &String {
    let s = String::from("Hello World!");
    &s
}

fn main() {
    let value = return_a_string();
    println!("{}", value);
}

错误原因:

在 return_a_string 函数中,s 的生命周期只持续到函数结束。value 将指向一块未定义的内存。

解决方法 1:

在 Rust 中,数据必须比它的引用活的时间长。return_a_string 函数不应该返回引用,而应该转移所有权。

fn return_a_string() -> String {
    let s = String::from("Hello World!");
    s
}

fn main() {
    let value = return_a_string();
    println!("{}", value);
}

解决方法 2:添加生命周期说明符

fn return_a_string() -> &'static str {
    "Hello World!"
}

fn main() {
    let value = return_a_string();
    println!("{}", value);
}

static 表示字符串在整个程序运行期间一直存在。

错误二:没有足够的权限

错误代码:

fn stringify_name_with_title(name: &Vec<String>) -> String {
    name.push(String::from("Esq."));
    let full_name = name.join(" ");
    full_name
}

fn main() {
    let name = vec![String::from("Ferris")];
    let first = &name[0];
    stringify_name_with_title(&name);
    println!("{}", first);
}

错误原因:

stringify_name_with_title 函数的入参 name 是一个不可变变量,没有修改权限。

解决方法:创建一个可变变量

fn stringify_name_with_title(name: &Vec<String>) -> String {
    let mut full_name = name.join(" ");
    full_name.push_str(" Esq.");
    full_name
}

fn main() {
    let name = vec![String::from("Ferris")];
    let full = stringify_name_with_title(&name);
    println!("{}", full);
}

错误三:别名和可变性

错误代码:

fn add_big_strings(dst: &mut Vec<String>, src: &[String]) {
    let largest: &String = dst.iter().max_by_key(|l| l.len()).unwrap();
    for s in src {
        if s.len() > largest.len() {
            dst.push(s.clone());
        }
    }
}

错误原因:

原本 dst 是一个可变的引用,但 largest 作为一个不可变的引用指向了 dst 中的一个元素。后面 push 就会发生错误,因为暂时没有 dst 的写权限了。

解决方法:

不创建有关 dst 的不可变引用了。

fn add_big_strings(dst: &mut Vec<String>, src: &[String]) {
    let largest_len = dst.iter().max_by_key(|l| l.len()).unwrap().len();
    for s in src {
        if s.len() > largest_len {
            dst.push(s.clone());
        }
    }
}

错误四:从集合中拷贝一个元素(转移所有权)

错误代码:

fn main() {
    let v: Vec<i32> = vec![0, 1, 2];
    let n_ref: &i32 = &v[0];
    let n: i32 = *n_ref;

    let v: Vec<String> = vec![String::from("Hello world")];
    let s_ref: &String = &v[0];
    let s: String = *s_ref;
}

错误原因:

不可以通过引用来获得所有权!

i32 具有 Copy Trait,在解引用的时候完成了复制。

String 没有 Copy Trait,在解引用时尝试获得所有权,失败。

解决方法:

通过 clone 创建一个字符串的副本。

fn main() {
    let v: Vec<i32> = vec![0, 1, 2];
    let n_ref: &i32 = &v[0];
    let n: i32 = *n_ref;

    let v: Vec<String> = vec![String::from("Hello world")];
    let s_ref: &String = &v[0];
    let s: String = v[0].clone();
}

错误五:对元组的引用

错误代码:

fn get_first(name: &mut (String, String)) -> &String {
    &name.0
}

fn main() {
    let mut name = (String::from("A"), String::from("B"));
    let first = get_first(&mut name);
    name.1.push_str(", Esq.");
    println!("{first} {}", name.1);
}

错误原因:

Rust 只关注函数的声明那一行,它发现 get_first 函数返回的是一个不可变的引用,它并不关心引用的是 name.0 还是 name.1,将 name.0 和 name.1 的写权限都暂时剥夺了,name.1 就不能修改了。

解决方法:

直接引用 name.0,因为元组中的每个元素的所有权都是独立的,这里只是将 name.0 和 name 的写权限暂时剥夺了,只修改 name.1 是不会报错的。

fn main() {
    let mut name = (String::from("A"), String::from("B"));
    let first = &name.0;
    name.1.push_str(", Esq.");
    println!("{first} {}", name.1);
}

错误六:修改数组中的元素

错误代码:

fn main() {
    let mut a = [0, 1, 2, 3];
    let x = &mut a[1];

    *x += 1;
    
    let y = &a[2];
    *x += *y;
    
    println!("{a:?}");
}

错误原因:

对 a 中元素创建了一个可变引用后,a 就暂时失去了读、写、拥有权限,只有 x 有权限。后面想再创建一个对 a 中元素的不可变引用,y 又想要获取 a 的读权限,就出错了。

修改:

fn main() {
    let mut a = [0, 1, 2, 3];
    let x = &mut a[1];

    *x += 1;
    
    // let y = &a[2];
    // *x += *y;
    
    println!("{a:?}");
}
前端埋点的实践 1、前言 开始正文前先介绍一下埋点的概念~,(熟悉的朋友可以略过) 前端埋点: 是一种手段,它的目的是上报相关行为数据,相关人员以数据为依据来分析产品在用户端的使用情况,根据分析出来的结果辅助产品优化、迭代。 BI:商业智能,公司内部做数据分析相关的部门。 2、背景 在流量红利逐渐消失的现在,数据的采集、分析和精细化的运营显得更加重要,所以埋点的需求在互联网产品中是很常见的,目的上面也提到了。我们的追求就是又快又好的做好埋点工作,但是现实却不那么美好;目前我们团队在前端埋点方面存在一些痛点: 在构造埋点字段 阅读详情

相关推荐

scGPT实战指南:如何用生成式AI加速你的单细胞多组学研究?

本文提供了scGPT在单细胞多组学研究中的实战指南。详细介绍了从环境部署、数据预处理到细胞类型注释与扰动预测等核心任务的操作流程。通过利用生成式AI和Transformer基础模型,scGPT能够显著加速分析,并提升细胞注释的准确性及基因调控网络推断的深度,为研究人员提供了强大的AI分析引擎。

weixin_29215815的博客 402

Rust 学习笔记结构:把编译错误整理成下一次能用的地图

把编译错误整理成一张可以反复查阅的地图:最小复现 + 我的误解 + 真正原因 + 修复方式 + 相似场景。AI 可以帮忙解释错误,但不要让它替自己完成理解——用自己的话写一遍解释,标记出自己之前的误解,把同类错误归到一起。我是自学的,没有老师带着梳理知识体系,只能靠自己的笔记来建立。学 Rust 最重要的不是背更多技巧,而是慢慢形成判断能力:看到报错时,能大概猜到是所有权、生命周期、trait 约束还是并发问题。

no1coder的博客 3430

setoolkit克隆网站获取用户信息

一、环境 kali、DVWA 二、步骤 首先打开kali,输入setoolkit 依次选择选项1-选项2-选项3-选项2 输入钓鱼网站的网址(默认为本地网址) 输入要克隆的网址URL 这里我的网址如图,将网址复制 然后模拟攻击场景,攻击者向受害者发送了一条钓鱼链接,此链接与DVWA的登陆页面完全一样,受害者点击之后并进行登陆信息 点击login之后,用户信息就被setool...

BeatRex的博客 2997

揭秘Rust所有权系统:3个你必须理解的关键概念,避免常见编译错误

掌握Rust所有权规则,轻松避免内存错误和编译困扰。本文解析所有权、借用与生命周期三大核心概念,助你写出安全高效的系统级代码。理解适用场景与关键优势,提升开发效率,值得收藏。

QuickDebug的博客 704

闲人闲谈PS之十二——WBS-BOM在装备制造项目中的实战解析

本文深入解析了WBS-BOM在装备制造项目中的核心应用。针对按订单设计/生产的行业痛点,WBS-BOM作为项目专属物料清单,完美连接SAP PS与PP模块,确保MRP能基于项目进行精准物料需求计算,实现从设计到生产的全链路项目化跟踪与管理。

weixin_29284885的博客 399

ITK-snap医学图像标注方法(超级详细)——保姆级

医学3D图像标注方法,非常详细,保姆级

jialiyk的博客 3万+

RUST所有权和借用

所有权和借用是 Rust 中保证内存安全的重要机制。所有权:每个值都有唯一的所有者,所有权可以转移。借用:通过不可变引用或可变引用来借用数据,避免转移所有权。借用规则:在同一作用域中,允许多个不可变引用,但最多只能有一个可变引用。理解所有权和借用将帮助你在编写 Rust 代码时避免内存错误,并充分利用 Rust 编译器的强大功能来捕获潜在的内存问题。

aliancn的收藏地 1165

publisher与subscriber话题的消息类型md5sum不一致问题

[ERROR] [1604235557.591296096]: Client [/range_vision_fusion_01] wants topic /detection/vision_objects to have datatype/md5sum [autoware_msgs/DetectedObjectArray/13415342e539aa36ea9a6f04ffaf39b4], but our version has [autoware_msgs/DetectedObjectArray/c16a

cxhmike的博客 6620

Rust所有权与借用规则深度解析:从踩坑到理解

刚开始学Rust的时候,我对所有权的概念完全懵圈。什么是所有权?为什么要有所有权?这跟我之前学的其他语言完全不一样啊!所有权是Rust用来管理内存的一套规则,不需要垃圾回收器就能保证内存安全。Rust的所有权和借用规则虽然一开始很难理解,但它们是Rust安全性和性能的关键。通过本文的介绍,希望能帮助大家对这些概念有更清晰的认识。保持学习,保持输出!今天终于搞懂了所有权,哭死!向大佬们低头学习!

no1coder的博客 1万+

通俗地解释一下 EMD(经验模态分解,Empirical Mode Decomposition)

EMD 就像把一碗“混在一起的面条”分成不同粗细的面条,方便你逐层分析每种波动。

qlkaicx的博客 1248

【NVMEM子系统】二、NVMEM驱动框架

该子系统整体架构不算太大,还是比较容易去理解的,下面我们一起去一探究竟!,该子系统主要用于实现EEPROMEfuse等非易失存储器的统一管理。在早期,像EEPROM驱动是存放于目录下,由于没有做到好的抽象,每次需要去访问相应内存空间,都需要去复制几乎一样的代码,去注册sysfs,这是一个相当大的抽象泄露。NVMEM子系统就是为了解决以往的抽象泄露问题。

Donge's Blog 1714

AI 解释 Rust 编译错误:把答案变成学习步骤

AI 解释 Rust 编译错误的正确用法,是把答案变成学习步骤。先理解编译器担心什么,再比较修复方案,最后自己修改并用验证。让 AI 当助教,而不是替你绕过编译器。

no1coder的博客 4993

纳米尺度仿真软件:Quantum Espresso_(13).非线性光学性质计算

通过 Quantum Espresso,可以高效地计算材料的非线性光学性质,包括二阶和三阶非线性极化率。这些性质在许多现代技术中具有重要的应用价值。在准备输入文件时,需要详细描述系统的晶格结构和原子位置,选择合适的基组和赝势,并设置计算参数和微扰设置。通过优化计算参数和使用并行计算,可以提高计算效率和精度。最后,使用适当的工具进行结果分析和可视化,可以更好地理解材料的非线性光学行为。

kkchenjj的博客 1277

Rust专项——Rust 所有权基础:安全内存管理的核心

摘要:本文深入讲解Rust所有权机制的核心概念,包括三大所有权规则、move与copy语义、借用与引用、切片以及常见错误修复方法。重点解析了所有权转移、克隆深拷贝、共享/可变借用的使用限制,并通过代码示例演示了如何避免悬垂引用和借用冲突。文章还提供了所有权相关的常见报错分析和练习题目,为后续学习生命周期和高级借用规则奠定基础。(150字)

红目香薰 1396

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

rust闪退修复工具_Rust的错误处理

Rust中的错误分成两种, 不可修复(unrecoverable)和可修复(recoverable)不可修复错误, 如访问超出数组范围的元素, 是需要被禁止的.可修复错误, 如文件不存在的一类错, 可以将问题提交给用户, 然后尝试重新操作来解决.不可修复错误rust中通过调用宏panic!实现, 可修复错误对应数据类型Result. 需要注意的是, 不同于其它编程语言, rust没有抛出异常(ex...

weixin_28804631的博客 3992

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Rust编程十大易犯错误与快速修复方法

Rust编程虽然具有挑战性,但通过理解并避免上述十大易犯错误,开发者可以更加高效地编写健壮、安全的代码。同时,随着经验的积累和对Rust语言特性的深入理解,开发者将能够更好地应对各种编程挑战。记住,遇到困难时不要害怕,查阅文档、寻求帮助并持续学习是进步的关键。

Yori_22的博客 1122

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Rust所有权机制在Web服务开发中的避坑指南

Rust Web开发中的所有权陷阱与解决方案 本文针对Rust Web开发中的所有权机制挑战,以Axum框架为例,分析了4个典型问题及解决方案: 请求体解析后的所有权失效:通过不可变引用(&T)或克隆(clone)复用数据,避免移动所有权导致变量失效。 共享状态的并发访问冲突:使用Arc+RwLock或原子类型实现线程安全的共享状态,解决多线程可变借用冲突。 异步任务生命周期超界:将被借用数据的所有权转移给异步任务,或使用Arc包装共享数据。 中间件所有权传递:通过Extension机制或请求扩展传

weixin_43578304的博客 6508

LLM 生成 Rust 代码:安全验证与自动修复的工程化方案

AI 辅助 Rust 代码生成的核心挑战在于编译期约束的满足率。本文构建了生成-验证-修复闭环系统,包含 Prompt 构造器、编译验证器和安全检查器三个核心模块。落地路线建议:第一步,在项目中引入和,建立编译错误的自动化提取流程;第二步,对 AI 生成的代码强制执行安全规则(禁止 unsafe、禁止 unwrap),通过 SafetyChecker 在 CI 中拦截违规代码;第三步,将修复迭代次数限制在 3 次以内,超过则回退到人工编写,避免无限修复循环;

no1coder的博客 5702

Qwen2.5-Coder-1.5B作品展示:Rust所有权错误推理与修正代码对比

本文介绍了如何在星图GPU平台自动化部署Qwen2.5-Coder-1.5B镜像,该镜像专精于代码推理与修复任务。通过展示其准确识别和修正Rust所有权错误的典型应用,例如分析代码片段并提供克隆或引用等解决方案,帮助开发者高效解决编程难题并深入理解语言特性。

JetFalcon67的博客 798

深入 Rust 内核:攻克生命周期常见错误与调试艺术

掌握 Rust 的生命周期,是一场思维模式的变革。你不再是命令式地管理内存,而是声明式地描述数据关系。当你下一次遇到生命周期错误时,请深吸一口气 🧘,不要慌张。记住这几个核心问题:1.数据的所有者是谁?2. **这个引用的“契约”是什么?它(&T)承诺活得不如(T)久吗?**3. **这个结构体(Struct<'a>)是否试图比它借用的数据(a)活得更久?** 4. \*\*我是不是在“过度使用”引用?转移所有权(String, \cloneArc)是否更简单?**

2501_92292137的博客 1092

AI 辅助 Rust 学习:编译器错误信息的智能解读与修复建议

Rust 编译器的错误信息已经是最友好的,但对初学者仍不够——"为什么"和"怎么改"之间的鸿沟需要额外知识来填补。AI 辅助工具的核心价值是缩短这个鸿沟:将编译器的技术描述翻译为可操作的修复建议,按优先级排序,并关联相关概念。本地规则引擎覆盖 80% 的高频错误,延迟低于 10ms,是日常开发的首选;远程 LLM 处理剩余 20% 的复杂场景,作为兜底方案。学习 Rust 的最大障碍不是语法,而是所有权思维——AI 工具不能替代理解,但能加速理解的过程。

no1coder的博客 4898

Rust专项——实战:字符串与集合的所有权/借用/生命周期模型

本文总结了Rust中所有权、借用和生命周期在字符串、向量和哈希表等数据结构中的应用实践。文章提出了"参数借用+返回所有权/视图"的设计模式:函数参数优先使用&str/&[T]等借用类型,需要所有权时在边界处转换;返回值根据使用场景选择拥有所有权(String/Vec)或视图(&str/&[T])。文章通过多个示例展示了该模式在API设计中的具体应用,并总结了常见错误的修复方法,包括所有权转移、借用冲突和临时值引用等问题。最后提供了两个实战练习,帮助读者掌握

红目香薰 911

所有权与借用机制:深入理解 Rust 内存安全核心

所有权与借用机制:深入理解 Rust 内存安全核心 【免费下载链接】rust-by-practice Learning Rust By Practice, narrowing the gap between beginner and skilled-dev through challenging examples, e...

gitblog_00659的博客 372

Rust Enhanced疑难问题解决:常见错误排查与修复指南

Rust Enhanced是Sublime Text 4的官方Rust语言插件,为开发者提供了强大的语法高亮、错误检查和代码提示功能。本文将帮助你快速定位并解决使用Rust Enhanced时遇到的常见问题,提升Rust开发体验。 ## 一、错误显示问题:如何开启实时错误提示? Rust Enhanced提供了两种错误显示方式:**行内提示**和**底部面板**。当代码出现错误时,默认配置下你

gitblog_00326的博客 399

Rust编程手册:从所有权到工程化实践全攻略

内存安全是系统编程语言设计的核心挑战之一。Rust 通过所有权系统在编译期保证内存安全,无需垃圾回收,同时兼顾高性能与并发安全。掌握 Rust 的关键在于理解所有权、借用与生命周期规则,以及运用 Cargo 工具链管理项目与依赖。从命令行工具到 Web 服务,Rust 正被广泛应用于嵌入式、音视频处理等场景。本文梳理了一本面向工程实践的 Rust 编程手册的核心内容,涵盖环境搭建、语法基础、错误处理、测试与常见编译错误排查,帮助开发者建立从入门到实战的完整路径。

weixin_34126557的博客 296

Rust 借用检查器深入理解:从编译错误到所有权心智模型

理解借用检查器的关键是建立所有权心智模型:值有唯一所有者,借用是临时访问权限,不可变借用多读共存,可变借用独占写。遇到借用冲突时,优先考虑三种解法:用索引代替引用、先收集再修改、用 entry API。生命周期标注只在函数签名返回引用时才需要显式写,大部分场景编译器能自动推断。unsafe 不是银弹,它绕过编译器检查但不绕过内存安全规则——用 unsafe 制造的 Bug 比 Rust 安全代码的 Bug 更难调试。

no1coder的博客 5103
上一篇: Rust 学习笔记:编程练习(一)
下一篇: Rust 学习笔记:关于切片的两个练习题
UestcXiye
博客等级 码龄8年 9029粉丝 1306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值