rust学习(第二章)

前置知识

  1. 栈和堆
    什么数据放栈里,什么数据放堆里?
    我们以为的:
  • 基本类型(primitive type)存储在栈上,对象存储在堆上;
  • 少量数据存储在栈上,大量的数据存储在堆上。

事实是:

在编译时,一切无法确定大小或者大小可以改变的数据,都无法安全地放在栈上,最好放在堆上。

比如一个函数,参数是字符串:

bash 复制代码
fn say_name(name: String) {}

// 调用
say_name("Lindsey".to_string());
say_name("Rosie".to_string());

字符串的数据结构,在编译时大小不确定,运行时执行到具体的代码才知道大小。比如上面的代码,"Lindsey" 和 "Rosie" 的长度不一样,say_name() 函数只有在运行的时候,才知道参数的具体的长度。所以,我们无法把字符串本身放在栈上,只能先将其放在堆上,然后在栈上分配对应的指针,引用堆上的内存。

只需要改动栈指针(stack pointer),就可以预留相应的空间;把栈指针改动回来,预留的空间又会被释放掉。

预留和释放只是动动寄存器,不涉及额外计算、不涉及系统调用,因而效率很高。所以理论上说,只要可能,我们应该把变量分配到栈上,这样可以达到更好的运行速度。

那为什么在实际工作中,我们又要避免把大量的数据分配在栈上呢?

这主要是考虑到调用栈的大小,避免栈溢出(stack overflow)。

一旦当前程序的调用栈超出了系统允许的最大栈空间,无法创建新的帧,来运行下一个要执行的函数,就会发生栈溢出,这时程序会被系统终止,产生崩溃信息。

过大的栈内存分配是导致栈溢出的原因之一,更广为人知的原因是递归函数没有妥善终止。一个递归函数会不断调用自己,每次调用都会形成一个新的帧,如果递归函数无法终止,最终就会导致栈溢出。

栈虽然使用起来很高效,但它的局限也显而易见。当我们需要动态大小的内存时,只能使用堆,比如可变长度的数组、列表、哈希表、字典,它们都分配在堆上。

栈上的内存在函数调用结束之后,所使用的帧被回收,相关变量对应的内存也都被回收待用。所以栈上内存的生命周期是不受开发者控制的,并且局限在当前调用栈。而堆上分配出来的每一块内存需要显式地释放,这就使堆上内存有更加灵活的生命周期,可以在不同的调用栈之间共享数据。

然而,堆内存的这种灵活性也给内存管理带来很多挑战。

如果手工管理堆内存的话,堆上内存分配后忘记释放,就会造成内存泄漏。一旦有内存泄漏,程序运行得越久,就越吃内存,最终会因为占满内存而被操作系统终止运行。如果堆上内存被多个线程的调用栈引用,该内存的改动要特别小心,需要加锁以独占访问,来避免潜在的问题。

比如说,一个线程在遍历列表,而另一个线程在释放列表中的某一项,就可能访问野指针,导致堆越界(heap out of bounds)。而堆越界是第一大内存安全问题。如果堆上内存被释放,但栈上指向堆上内存的相应指针没有被清空,就有可能发生使用已释放内存(use after free)的情况,程序轻则崩溃,重则隐含安全隐患

小结

对于存入栈上的值,它的大小在编译期就需要确定。栈上存储的变量生命周期在当前调用栈的作用域内,无法跨调用栈引用。

堆可以存入大小未知或者动态伸缩的数据类型。堆上存储的变量,其生命周期从分配后开始,一直到释放时才结束,因此堆上的变量允许在多个调用栈之间引用。但也导致堆变量的管理非常复杂,手工管理会引发很多内存安全性问题,而自动管理,无论是 GC 还是 ARC,都有性能损耗和其它问题。

一句话对比总结就是:栈上存放的数据是静态的,固定大小,固定生命周期;堆上存放的数据是动态的,不固定大小,不固定生命周期。

相关推荐
框架主义者7 分钟前
N2N Maid - 一个开源多端的 N2N 图形界面
计算机网络·rust
Gsen28199 分钟前
AI大模型从0到1记录学习 大模型技术之机器学习 day60-day69
人工智能·学习·机器学习
Arciab12 分钟前
51单片机学习板PCB制作
嵌入式硬件·学习·51单片机
小智RE0-走在路上13 分钟前
Python学习笔记(10) -- 异常,模块,包
笔记·python·学习
TechNomad20 分钟前
排序算法:希尔排序算法
数据结构·算法·排序算法
im_AMBER21 分钟前
Leetcode 83 使数组平衡的最少移除数目中等相关标签 | 尽可能使字符串相等
数据结构·c++·笔记·学习·算法·leetcode
xian_wwq23 分钟前
【学习笔记】安全模型
笔记·学习
理人综艺好会27 分钟前
Redis学习之单线程
redis·websocket·学习
先生沉默先30 分钟前
c#Socket学习,使用Socket创建一个在线聊天,需求分析与创建项目,数据结构创建(1)
数据结构·学习·c#
Bdygsl31 分钟前
数据结构 —— 顺序表
数据结构·链表