【小测试】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 ...
随机推荐
- Linux上非root用户jdk环境变量配置
1.设置用户环境变量vi .bash_profile 或者是 vi ~/.bashrc 2.JAVA_HOME=/home/sgmm/jdk1.6.0_13 CLASSPATH=$JAVA_HOME/ ...
- Blazor实现菜单动画
想到动画,你可能会去安装Blazor的动画组件BlazorAnimate,然后使用它.本人初学,暂时我也不知道原理,先不用组件,自己实现吧.虽然项目中我用了AntDesignBlazor,但是我忘了使 ...
- 牛客 | 小G的约数引起的对于 整数分块 学习
整除分块是个啥:要求\(∑_{i = 1}^n{n/i}\) 的值,这时候暴力需要O(n)的时间.由于这个区间是连续的,且'/'是向下取整,当i不能整除k时,n/i会等于最小的i(也就是区间最左边的值 ...
- 使用 Serverless Devs 插件快速部署前端应用
作者| 邓超 Serverless Devs 开源贡献者 背景 我们在 上文 [Aliyun] [FC] 如何使用 @serverless-devs/s 部署静态网站到函数计算 中,详细的介绍了如何通 ...
- 【调试】ftrace(二)新增跟踪点
内核的各个子系统已经有大量的跟踪点,如果这些跟踪点无法满足工作中的需求,可以自己手动添加跟踪点. 添加跟踪点有两种方式,一种是仿照events/目录下的跟踪点,使用TRACE_EVENT() 宏添加. ...
- mock.js使用
前后端联调必备技术之Mock讲解 什么是Mock数据? 处于开发环境模拟接口返回的数据(用于开发状态后端还没给接口) 不会影响生产环境,只是方便我们还没与后端交互时,不阻塞我们开发流程 mock数据好 ...
- vue 使用print.js实现前端打印功能
https://blog.csdn.net/cccdf_jjj/article/details/99563682 插件vue-print-nb实现前端打印当前页面功能 https://blog.csd ...
- node开发概述
一.Node开发概述 1. 为什么要学习服务器端开发 能够与后端程序员更加紧密的配合 网站业务逻辑前置,学习前端技术需要后端技术支撑(ajax) 扩宽知识视野,能够站在更高的角度审视整个项目 2. 服 ...
- RL 基础 | 如何搭建自定义 gym 环境
需实现的方法: __init__(self): 需定义 action_space 和 observation_space,使用 space.Box 之类来表示(from gym import spac ...
- spring--CGLIB动态代理的实现原理
CGLIB(Code Generation Library)是一个强大的.高性能.高质量的代码生成库,它可以在运行时扩展 Java 类和实现 Java 接口.CGLIB 动态代理是基于继承的方式来实现 ...
