【小测试】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 ...
随机推荐
- java反射机制原理剖析
当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是java有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有反射也就没有框架,现有的框 ...
- Spark 覆盖写Hive分区表,只覆盖部分对应分区
要求Spark版本2.3以上,亲测2.2无效 配置 config("spark.sql.sources.partitionOverwriteMode","dynamic& ...
- OpenSSL 升级、回滚
ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with ...
- 消息驱动 —— SpringCloud Stream
Stream 简介 Spring Cloud Stream 是用于构建消息驱动的微服务应用程序的框架,提供了多种中间件的合理配置 Spring Cloud Stream 包含以下核心概念: Desti ...
- python 读取数据调翻译更新表字段
import time import requests import pymysql import datetime import random from hashlib import md5 imp ...
- 电子签章Java后端与前端交互签名位置计算
电子签章过程中存在着在网页上对签署文件进行预览.指定签署位置.文件签署等操作,由于图片在浏览器上的兼容性和友好性优于PDF文件,所以一般在网页上进行电子签章时,会先将PDF文件转换成图片,展示给用户. ...
- 服务器上TIME_WAIT过多怎么处理
正常情况下,TIME_WAIT是需要存在的 为了保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文,服务 ...
- WPF ElementHost 内存泄露问题
无意中发现,WPF ElementHost 控件如果未正确释放,会存在内存泄露问题.解决方法如下: xaml代码: <Grid x:Name="grid"> <W ...
- 清洁低碳环保新能源,3D 光伏与光热发电站可视化
前言 碳达峰.碳中和成为今年两会"热词",在国家政府工作报告中指出,扎实做好碳达峰.碳中和各项工作,制定 2030 年前碳排放达峰行动方案,优化产业结构和能源结构,实现低碳环保节能 ...
- windows无法远程访问liunx的mysql解决方案(8.0.27版本)
一.安装后mysql后发现windows上的无法正常访问,报错如下: 不管是navicat软件,还是使用python的pymsql进行连接 1.navicat软件如下:"Access den ...
