当前位置: 首页 > article >正文

Rust 学习笔记:关于智能指针的练习题

Rust 学习笔记:关于智能指针的练习题

  • Rust 学习笔记:关于智能指针的练习题
    • 问题一
    • 问题二
    • 问题三
    • 问题四
    • 问题五
    • 问题六
    • 问题七
    • 问题八
    • 问题九
    • 问题十

Rust 学习笔记:关于智能指针的练习题

参考视频:

  1. https://www.bilibili.com/video/BV1SJ9vYsEfR
  2. https://www.bilibili.com/video/BV1Q79vYdEGx
  3. https://www.bilibili.com/video/BV1Q79vYdEgo
  4. https://www.bilibili.com/video/BV1Rg9vYhExC
  5. https://www.bilibili.com/video/BV1dLRVYrEfQ
  6. https://www.bilibili.com/video/BV1RGRnYoEiJ

问题一

以下程序能否通过编译?若能,输出是?

fn main() {let mut n = 1;let b = Box::new(&mut n);**b += 1;println!("{}", n);
}

答:可以通过编译。输出为 2。

问题二

假设我们有一个程序,其中有一个变量:

let x = [Box<(usize, usize)>; 4] = /* ... */

对于一个 64 位架构的编译目标,x 在栈上所占用的最小内存大小是多少?

答:32 字节。

在 Rust 中,变量 x 的类型为 [Box<(usize, usize)>; 4],这是一个包含 4 个元素的数组,每个元素是一个 Box<(usize, usize)>。Box<T> 是一个智能指针,它在栈上仅存储一个指针,在 64 位架构上,指针的大小固定为 8 字节,故数组大小 = 4 * 8 = 32 字节。

问题三

以下程序能否通过编译?若能,输出是?

use std::ops::Deref;#[derive(Copy, Clone)]
struct AccessLogger(i32);impl Deref for AccessLogger {type Target = i32;fn deref(&self) -> &Self::Target {println!("deref");&self.0}
}fn main() {let n = AccessLogger(-1);let x = *n + 1;let n2 = n;println!("{} {}", x, *n);
}

答:可以通过编译。输出为:

deref
deref
0 -1

问题四

以下程序能否通过编译?若能,输出是?

struct Example(i32);impl Drop for Example {fn drop(&mut self) {self.0 += 1;println!("drop {}", self.0);}
}fn main() {let e = Example(0);drop(e);drop(e);
}

答:不能通过编译。

问题五

在这里插入图片描述

答:{ s }、drop(s)、(|_|())(s)。

第一个利用了作用域,s 变量离开作用域时自动被清除。

第二个调用了 std::mem::drop 函数,显式销毁了 s 变量。

第三个是一个空闭包, 闭包获取了 s 的所有权,离开闭包时 s 被销毁。

第四个是不被允许的。

问题六

以下程序能否通过编译?若能,输出是?

use std::rc::Rc;fn main() {let n = Rc::new(1);let mut n2 = Rc::clone(&n);*n2 += 1;println!("{}", n);
}

答:不能通过编译。

Rc::clone 是浅拷贝,并没有获取值的所有权。

问题七

以下程序能否通过编译?若能,输出是?

use std::rc::Rc;struct Example;impl Drop for Example {fn drop(&mut self) {println!("drop");}
}fn main() {let x = Rc::new(Example);let y = Rc::clone(&x);println!("A");drop(x);println!("B");drop(y);println!("C");
}

答:可以通过编译。输出为:

A
B
drop
C

销毁 x 时,对 Example 的引用计数为 1。只有当 y 也被销毁时,引用计数才为 0,执行 drop 方法。

问题八

以下哪项最好地描述了 Rust 中内部可变性的概念?

A. 将 unsafe 代码包装在安全的 API 中
B. 允许借用检查器在运行时强制执行内存安全
C. 允许数据结构内部的数据被修改
D. 允许通过不可变引用修改数据

答:D。

问题九

在这里插入图片描述

答:RefCell<usize>。

问题十

考虑以下未检查内部值是否被借用的错误 RefCell 实现:

use std::cell::UnsafeCell;struct BadRefCell<T>(UnsafeCell<T>);impl<T> BadRefCell<T> {pub fn borrow_mut(&self) -> &mut T {unsafe { &mut *self.0.get() }}
}

假设我们有如下 BadRefCell:

    let v = BadRefCell(UnsafeCell::new(vec![1, 2, 3]));

以下哪个代码片段在使用此 API 时会违反内存安全?

A.

    drop(v.borrow_mut());drop(v.borrow_mut());

B.

    let v1 = v.borrow_mut();let v2 = v.borrow_mut();v1.push(4);v2.push(5);

C.

    let v1 = v.borrow_mut();let n = &v1[0];v.borrow_mut().push(0);println!("{}", n);

D.

    v.borrow_mut().push(0);let n = v.borrow_mut()[0];println!("{}", n);

答:C。

获取 v 的可变引用后,向其中插入数据,可能会变更值在堆上的位置。此时再访问 n,可能发生内存泄漏,使得 n 变成一个悬垂引用。

数组 [1, 2, 3] 太小了,插入 1 个元素不一定会导致位置变化。我们改用一个包含 100000 个元素的数组,完整代码如下:

use std::cell::UnsafeCell;struct BadRefCell<T>(UnsafeCell<T>);impl<T> BadRefCell<T> {pub fn borrow_mut(&self) -> &mut T {unsafe { &mut *self.0.get() }}
}fn main() {let v = BadRefCell(UnsafeCell::new(vec![1; 10000]));let v1 = v.borrow_mut();let n = &v1[0];v.borrow_mut().push(0);println!("{}", n);
}

运行结果:

在这里插入图片描述

理论上应该打印 1。显然这段代码违反内存安全,但还是通过了 Rust 的编译和运行时检查。

http://www.lryc.cn/news/2401870.html

相关文章:

  • 6.RV1126-OPENCV 形态学基础膨胀及腐蚀
  • 筑牢企业网管域安全防线,守护数字核心——联软网管域安全建设解决方案
  • 【目标检测】backbone究竟有何关键作用?
  • 一个小小的 flask app, 几个小工具,拼凑一下
  • 对抗性提示:大型语言模型的安全性测试
  • 好得睐:以品质守味、以科技筑基,传递便捷与品质
  • docker-部署Nginx以及Tomcat
  • Servlet 体系结构
  • 蒙特卡罗模拟: 高级应用的思路和实例
  • Java集合中Stream流的使用
  • Python批量转换Word、Excel、PPT、TXT、HTML及图片格式到PDF,包含错误处理和日志记录功能
  • 数据分析Agent构建
  • vscode配置lua
  • 【笔记】MSYS2 的 MINGW64 环境 全面工具链
  • 国内头部的UWB企业介绍之品铂科技
  • Prj10--8088单板机C语言8259中断测试(2)
  • 《前端面试题:CSS对浏览器兼容性》
  • 使用 Docker Compose 安装 Redis 7.2.4
  • 35.x64汇编写法(二)
  • 安全大模型的思考
  • SQL Server 2025 预览版新功能
  • NineData云原生智能数据管理平台新功能发布|2025年5月版
  • 数学复习笔记 25
  • Linux可执行文件ELF文件结构
  • RAG:大模型微调的革命性增强——检索增强生成技术深度解析
  • DisplayPort 2.0协议介绍(1)
  • I2C通信讲解
  • 【信息系统项目管理师-选择真题】2025上半年(第一批)综合知识答案和详解
  • ABP VNext 在 Kubernetes 中的零停机蓝绿发布
  • linux 故障处置通用流程-36计-14-27