开启RefCell debug_refcell feature查看借用冲突位置

ops/2024/10/25 7:50:26/

文章目录

  • 背景
  • 分析
  • 解决方法

本文解决两个问题:

  • 开启rust源码库中的feature
  • 开启debug_refcell feature的方法查看 borrow 借用冲突的位置

背景

使用 RefCell 来实现内部可变性是在 Rust 开发中常用的方式,但是当逻辑复杂起来,常常会有可变借用和不可变借用之间的冲突。在默认情况下,Rust只会报错最后冲突的位置,即第7行,而第6行不会在错误堆栈出现。如果逻辑复杂起来,b的位置不在这么明显的位置,根本无从查起。
在这里插入图片描述

分析

查看 borrow() 和 borrow_mut() 的源码,它们分别是调用了 try_borrow() 和 try_borrow_mut(),在 try_borrow() 和 try_borrow_mut() 里面,发现了这么一段代码:

rust"> Some(b) => {#[cfg(feature = "debug_refcell")]{// `borrowed_at` is always the *first* active borrowif b.borrow.get() == 1 {self.borrowed_at.set(Some(crate::panic::Location::caller()));}}// SAFETY: `BorrowRef` ensures that there is only immutable access// to the value while borrowed.let value = unsafe { NonNull::new_unchecked(self.value.get()) };Ok(Ref { value, borrow: b })}None => Err(BorrowError {// If a borrow occurred, then we must already have an outstanding borrow,// so `borrowed_at` will be `Some`#[cfg(feature = "debug_refcell")]location: self.borrowed_at.get().unwrap(),}),

可以看到 RefCell 有 borrowed_at 这么一个字段,当是 Some 并且 b.borrow.get() 是1的时候,设置了 borrowed_at;当是 None 的时候,给 BorrowError 传了 borrowed_at这个参数。

我们可以合理推测,borrowed_at是第一个被借用的"变量"。来看看 RefCell 结构体定义的地方:

rust">pub struct RefCell<T: ?Sized> {borrow: Cell<BorrowFlag>,// Stores the location of the earliest currently active borrow.// This gets updated whenever we go from having zero borrows// to having a single borrow. When a borrow occurs, this gets included// in the generated `BorrowError`/`BorrowMutError`#[cfg(feature = "debug_refcell")]borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,value: UnsafeCell<T>,
}

注释解释的很清楚了,borrowed_at就是最早发生的借用,当借用冲突发生的时候,它可以在错误中生成。

那么就是用 borrowed_at 查看冲突的位置了,但是要用它就需要打开 debug_refcell feature,默认情况下显然没有开启(因为上面的错误信息并没有最早发生借用的位置),而直接在项目的 Cargo.toml 中添加 debug_refcell 是不行的,因为这只是在我们自己的项目中开启feature,rust库是不知道的。

接下来就是要解决怎么在 rust源码库中开启指定 feature。

解决方法

询问 ChatGPT,需要在cargo build的时候编译源码库,并为其指定feature:

cargo +nightly run --target=x86_64-pc-windows-msvc -Zbuild-std -Zbuild-std-features="core/debug_refcell"

这次报错信息出现了最早借用的位置,即第6行。
在这里插入图片描述

这种方式需要使用 nightly 版本的rust编译器

rustup toolchain install nightly
rustup component add rust-src --toolchain nightly-x86_64-pc-windows-msvc
# 验证 nightly 版本是否安装
# 不需要切换到 nightly,上面的命令指定了这次编译的编译器版本是 nightly
rustup toolchain list 

如果你的项目环境是 no_std,需要去指定编译的库(排除std)

cargo +nightly build --release --target thumbv8m.main-none-eabihf -Zbuild-std=core,alloc -Zbuild-std-features="core/debug_refcell"

http://www.ppmy.cn/ops/128274.html

相关文章

C++(面向对象、封装性、构造函数)

面向对象 三大特征&#xff1a;封装、继承、多态 C中的class是从C的struct扩展来的&#xff0c;两者的区别是默认访问权限不同。 struct的默认访问权限是公有的public class默认访问权限是私有的private 访问权限 类的内部派生类&#xff08;子类&#xff09…

RK3568开发板(debain系统)与Ubuntu使用nfs共享文件

VMware虚拟机 Ubuntu18.04 【网络配置陈桥接模式】 RK3568开发板【我是用讯为的RK3568】 网线连接路由器或者和电脑直连&#xff08;J13网口&#xff09; 1、Ubuntu上nfs服务器安装 1.1、命令如下&#xff1a; sudo apt-get update sudo apt-get install nfs-kernel-server1…

缓存预取文章比较分析

这篇文章主要记录调研的cache prefetch部分有价值的论文&#xff0c;并给出一些总结 Baleen 核心内容 ML learning-based admission policy prefetch.exploit a new cache residency model to guide model training. 首先对 access pattern 进行了统计分析&#xff0c;提取…

【火山引擎】语音识别 |流式语音识别 | python

目录 一 准备工作 二 流式语音识别 三 实践 模型广场:账号登录-火山引擎

软考——计算机网络概论

文章目录 &#x1f550;计算机网络分类1️⃣通信子网和资源子网2️⃣网络拓扑结构3️⃣ 计算机网络分类3&#xff1a;LAN MAN WAN4️⃣其他分类方式 &#x1f551;OSI 和 TCP/IP 参考模型1️⃣OSI2️⃣TCP/IP&#x1f534;TCP/IP 参考模型对应协议 3️⃣OSI 和 TCP/IP 模型对应…

CSP-S 信心赛 飚速布 题解

飚速布 2024.10.24 T4 题意 n n n 个数 a 1 , a 2 , a 3 , … , a n a_1, a_2, a_3, \dots, a_n a1​,a2​,a3​,…,an​。有 m m m 轮操作&#xff0c;第 i i i 轮操作选择恰好 k k k 个数使它 1 1 1。 设 U [ 1 , n ] ∩ N U [1, n] \cap \mathbb{N} U[1,n]∩N&a…

java项目使用HttpServletRequest request接参,怎么获取参数的值,怎么获取form值,怎么获取body值

java项目使用HttpServletRequest request接参,怎么获取参数的值,怎么获取form值,怎么获取body值 1.假设你的方法是这个样子的 public ResponseEntity<String> GetUserInfo(HttpServletRequest request)

分布式-单元化架构1

一 两地三中心 1.1 两地三中心* 两地指的是两个城市&#xff1a;同城&#xff0c;异地。三中心指的是三个数据中心&#xff1a;生产中心、同城容灾中心、异地容灾中心。 在同一个城市或者临近的城市建设两个相同的系统&#xff0c;双中心具备相当的业务处理能力&#xff0c;…