【小测试】rust中的数组越界——好吧,这下证明rust不是零成本抽象了吧
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!
1.编译期发现的数组越界
在数组下标是常量的情况下,编译期就会发现。
- cargo new arr_test
- 在arr_test/src/main.rs中写入:
fn main() {
let mut arr : [i64;10] = [0,1,2,3,4,5,6,7,8,9];
println!("{:?}",arr[10]);
}
- 执行cargo run
- 编译器错误信息为:
error: this operation will panic at runtime
--> src/main.rs:10:21
|
3 | println!("{:?}",arr[10]);
| ^^^^^^^ index out of bounds: the length is 10 but the index is 10
|
= note: `#[deny(unconditional_panic)]` on by default
warning: `arr_test` (bin "arr_test") generated 1 warning
error: could not compile `arr_test` due to previous error; 1 warning emitted
2.运行期的数组越界
- main.rs的内容为:
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
let mut arr : [i64;10] = [0,1,2,3,4,5,6,7,8,9];
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
let ts = since_the_epoch.as_secs() as usize;
let idx = ts % 10; //下标的数据类型必须是usize
println!("{:?}", arr[idx+9]); //90%的概率会越界
}
- cargo run:
thread 'main' panicked at 'index out of bounds: the len is 10 but the index is 13', src/main.rs:19:22
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
由此说明: rust加上了运行期的越界检查,以此避免异常的行为。
那么,release版本也会做越界检查吗?
- cargo build --release
- ./arr_test/target/release/arr_test
发现即便是release版本,也是有越界检查的。
由此证明:rust并非零成本抽象,为了做越界检查,编译器一定会在每次访问数组下标的时候加上两条越界检查指令。
3.跳过越界检查
- 直接加上unsafe并不行:
fn main(){
//...
unsafe {
println!("{:?}", arr[idx+9]);
}
}
编译器报错:
warning: unnecessary `unsafe` block
--> src/main.rs:20:5
|
20 | unsafe {
| ^^^^^^ unnecessary `unsafe` block
|
= note: `#[warn(unused_unsafe)]` on by default
只有用上裸指针,rust才认为是unsafe:
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
let mut arr : [i64;10] = [0,1,2,3,4,5,6,7,8,9];
let start = SystemTime::now();
let since_the_epoch = start
.duration_since(UNIX_EPOCH)
.expect("Time went backwards");
let ts = since_the_epoch.as_secs() as usize;
let idx = ts % 10; //下标的数据类型必须是usize
unsafe {
let ref1_at_0 = &mut arr[0];
let ptr2_at_0 = ref1_at_0 as *mut i64;
let ptr3_at_1 = ptr2_at_0.add(idx+9);
println!("{:?}", *ptr3_at_1);
}
}
上面的代码果然成功越界,没有触发panic,打印了一个随机的整形值。
因此:
- 假设用rust数组写一个什么local cache的服务,则每次下标访问必然导致额外的越界检查的开销;
- 避免这种开销的办法就是在unsafe代码中使用裸指针
have fun
【小测试】rust中的数组越界——好吧,这下证明rust不是零成本抽象了吧的更多相关文章
- Java中的数组越界问题
Java中数组初始化和OC其实是一样的,分为动态初始化和静态初始化, 动态初始化:指定长度,由系统给出初始化值 静态初始化:给出初始化值,由系统给出长度 在我们使用数组时最容易出现的就是数组越界问题, ...
- C++中的数组越界
C++中数组发生越界错误时, compiling过程不会报错, linking过程也不会报错, 会在executing过程中发生意想不到的错误或问题.
- Objc中处理数组越界的一种办法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) Objc的数组如果在访问时索引非法,则会抛出NSRangeEx ...
- 刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?
我为什么学Rust? 2019年6月18日,Facebook发布了数字货币Libra的技术白皮书,我也第一时间体验了一下它的智能合约编程语言MOVE,发现这个MOVE是用Rust编写的,看来想准确理解 ...
- Rust中的Slices
这个slice切片,python中有,go中有, 但确实,Rust中最严格. 精彩见如下URL: Rust 程序设计语言(第二版) 简体中文版 · GitBook (Legacy) https://k ...
- 【译】理解Rust中的Futures (一)
原文标题:Understanding Futures In Rust -- Part 1 原文链接:https://www.viget.com/articles/understanding-futur ...
- Rust中的宏:声明宏和过程宏
Rust中的声明宏和过程宏 宏是Rust语言中的一个重要特性,它允许开发人员编写可重用的代码,以便在编译时扩展和生成新的代码.宏可以帮助开发人员减少重复代码,并提高代码的可读性和可维护性.Rust中有 ...
- PHP中使用PDO操作事务的一些小测试
关于事务的问题,我们就不多解释了,以后在学习 MySQL 的相关内容时再深入的了解.今天我们主要是对 PDO 中操作事务的一些小测试,或许能发现一些比较好玩的内容. 在 MyISAM 上使用事务会怎么 ...
- java中的数组 和 封装
package com.aaa.zxf; /** * 一. 普通java项目 导入测试类的方法. * ideal 中 java 项目中导入测试类的方法 手动写入 * import org.junit. ...
- iOS如何彻底避免数组越界
我们先来看看有可能会出现的数组越界Crash的地方: ? 1 2 3 4 5 6 7 - (void)tableView:(UITableView *)tableView didSelectRowAt ...
随机推荐
- Taro架构构析(2):Taro 设计思想及架构
从之前微信公众号的开发经验来说,以及腾讯开放平台的接入 等经验来看,一直对腾讯的开放文档 有心理阴影. 微信小程序从文件组织上看,一个小程序页面或组件,需要同时包含 4 个文件:脚本逻辑.样式.模板以 ...
- Taro架构构析(1):多端框架分析,Taro WePY uni-app对比
多端框架分类 全包型 这类框架最大的特点就是从底层的渲染引擎.布局引擎,到中层的 DSL,再到上层的框架全部由自己开发,代表框架是 Qt 和 Flutter.这类框架优点非常明显:性能(的上限)高:各 ...
- 单向数据流-从共享状态管理:flux/redux/vuex漫谈异步数据处理
不管是Vue,还是 React,都需要管理状态(state),比如组件之间都有共享状态的需要. 什么是共享状态? 比如一个组件需要使用另一个组件的状态,或者一个组件需要改变另一个组件的状态,都是共享状 ...
- Axure 形状交互
- 文心一言 VS 讯飞星火 VS chatgpt (180)-- 算法导论13.4 3题
三.用go语言,在练习13.3-2 中,将关键字 41.38.31.12.19.8 连续插入一棵初始的空树中,从而得到一棵红黑树.请给出从该树中连续删除关键字 8.12.19.31.38.41 后的红 ...
- Android 启动优化(二) - 有向无环图的原理以及解题思路
Android 启动优化(一) - 有向无环图 Android 启动优化(二) - 拓扑排序的原理以及解题思路 Android 启动优化(三) - AnchorTask 使用说明 Android 启动 ...
- MIGO BAPI_GOODSMVT_CREATE创建及增强
1.MIGO过账BAPI新增字段 BAPI新增收货行号字段,保存外围系统的数据 1.1.MATDOC表新增收货行号 1.2.MSEG表新增收货行号 创建DDL视图用于扩展NSDM_E_MSEG 1.3 ...
- 数据结构——AVL树
AVL树是一种特殊的二叉查找树,其特征在于:对所有节点来说,其左子树和右子树间的高度差小于等于1.本文简要总结下AVL树的几种基本操作. 节点结构体定义 typedef struct Node_s { ...
- 【AcWing】第6场周赛 B题 3734. 求和 (思维)
AcWing 3734. 求和 其实这道题并不难,只是思维性很强! 因为 \(a\) 的各个数位不包含除了 \(4\) 和 \(7\) 以外的其他数字. 仔细观察数据会发现因为 \(1\le l \ ...
- Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final) 个人题解(A - D)
1443A. Kids Seating 题意: 给你一个整数n,现在你需要从编号 \(1\) ~ $4 ⋅ n \(中选出\)n\(个编号使得这些编号之间\)g c d ≠ 1$ ,不能整除. 看了半 ...
