Rust所有权及引用

Rust 所有权和借用

Rust之所以可以成为万众瞩目的语言, 就是因为其内存安全性. 在以往内存安全几乎全都是通过GC的方式实现, 但是GC会引来性能、CPU以及Stop The World等问题, 在需要高性能的场景是不可以接受的,因此Rust使用一种与众不同的方式 解决内存安全问题: 所有权机制

Rust所有权

所有程序都必须和计算机的内存打交道, 如何从RAM中申请空间存放程序运行所需要的数据, 在不需要是回收内存空间, 成为了关键, 在计算机编程语言不断进化的过程中出现了三种解决方案:

垃圾回收机制(GC) , 程序运行时RunTime 通过三色标记 引用计数 分代回收等算法 回收空闲内存 : Go Python Java

手动管理内存的分配和释放, 编写通过函数调用的方式申请释放内存 : C malloc() free(), C++ new() delete()

通过所有权机制管理内存, 在程序编译期间 确定内存申请 释放的时间, 将相关的数据硬编码到二进制程序中, 在程序运行期间不会有任何性能上的损耗

一段内存不安全的代码 int* foo() { int a; // 变量a的作用域开始 a = 100; char *c = "xyz"; // 变量c的作用域开始 return &a; } // 变量a和c的作用域结束

​ 这段C代码是可以顺利编译通过的 foo函数返回一个int指针类型, 但是变量a和c是foo函数内的局部变量, 我们都知道 函数和函数内的局部变量 都是存储在栈当中的, 当foo函数执行完成后 局部变量a,c及函数foo 在栈内申请的内存 就已经被回收了, 此时返回变量a的指针, 从而形成了悬空指针 (悬垂指针, 野指针) 因为a申请的内存数据在foo函数结束是已经被回收, 此时返回a的指针 指向的内存地址已经被回收或者被其他程序使用, 如果这块地址再次被其他程序申请到并放入数据, 那就跟我们程序预期的效果产生差异,容易导致程序崩溃.

例如: a程序中a的数据是100 , 回收后被其他程序申请存入数据为 "malloc"。

​ 我们再来看一下变量c, 变量c的问题在于内存的浪费, 也是对栈的空间的浪费, c变量申请的内存在他声明完成后没有任何操作, 但是他回收的时间需要在foo函数结束是才进行回收 产生了资源的浪费

​ 内存安全的问题一直都是令开发者头疼的问题, 所以如何保证内存安全成为我们对技术深度评判标准之一, Rust的所有权机制将解决大部分内存安全问题, 想要保证内存安全我们就需要对 堆 栈有足够的认知

堆 和 栈

堆和栈是编程语言最核心的两个数据结构, 在许多编程语言我们不需要深入了解, 因为GC会偷偷的无感知的帮我们进行内存的回收, 这也意味着性能的瓶颈, 但是对于Rust这种系统编程语言, 数据值位于栈 或 堆 上是很重要的, 因为他大大的影响程序运行时的性能

堆栈实际上都是我们RAM

栈 是按照顺序且连续存储值 并以相反的数据取值, 先进后出, 存储数据为进栈 , 取出数据为出栈。 栈中的数据值所申请的内存大小必须是已知的固定的内存空间, 如果数据值大小是未知的, 那么取出数据时, 你无法取出你想要的数据。

栈 通常存储的数据是 编程语言的内置的基本类型的数据 i32 i64 f32 f64 &str bool 、 函数、 函数内的局部变量 、堆指针地址、元祖

ulimit -s 用于查看操作系统的栈空间 间接的说明栈空间是有限的 如果申请栈内存空间超出栈 就会发生栈溢出 程序崩溃、Go内存逃逸分析 等场景

每一个程序运行时操作系统都会为其分配栈的内存空间 1-8M , 通常情况下不会出现栈溢出 如果出现死循环、深递归的时候就极有可能出现程序崩溃。

对比着栈来理解堆 更容易理解一些

栈是由cpu寄存器来访问控制回收, 堆是由开发者来控制堆内存的回收

栈中存储的数据值都是已知大小的数据, 堆内可以存储未知大小的动态数据 相对灵活 .

栈申请的内存用完立即释放, 堆内存需要根据生命周期和GC算法释放内存

栈是连续的内存空间, 堆是不连续的 很有可能会产生内存碎片 无法回收造成浪费

栈的空间是有限的, 堆的空间可以认为是无限的

栈为什么会比堆快

1.cpu高速缓存会缓存栈内的数据 不会缓存堆内的数据 跟他们的存储规则有关

2.栈是直接寻址 申请只存只需要移动一个指针即可, 堆是间接寻址的 首先要去栈内取得变量的堆指针, 才可以获取数据。

3.栈是由cpu的寄存器直接访问控制的

4.栈在程序开始运行就已经开辟好了内存空间, 而堆需要在程序运行时 运行到对应到指定位置才开辟内存空间

5.入栈比堆分配内存快, 因为入栈操作系统无需分配新的内存空间,只需将新数据放入栈顶

所有权原则

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzgdyf.html