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,都有性能损耗和其它问题。

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

相关推荐
完球了5 分钟前
【Day03-MySQL单表】
数据库·笔记·学习·mysql·sql8.0
今天开始奋斗吧15 分钟前
docker
linux·服务器·学习
Qhumaing30 分钟前
C语言PTA-计算最大游戏胜率
c语言·开发语言·学习·pta
sjsjs1132 分钟前
【贪心】【数据结构-小根堆,差分】力扣2406. 将区间分为最少组数
数据结构·算法·leetcode
酒饮微醉-1 小时前
论文阅读--Planning-oriented Autonomous Driving(二)
论文阅读·笔记·学习·自动驾驶
你可以叫我仔哥呀1 小时前
学习笔记JVM篇(五)
jvm·笔记·学习
码农0001 小时前
nginx学习笔记
笔记·学习·nginx
码上一元1 小时前
【百日算法计划】:每日一题,见证成长(019)
java·数据结构·算法
weixin_750335522 小时前
Datawhale X 南瓜书 task02学习笔记
笔记·python·学习
还听珊瑚海吗2 小时前
数据结构——二叉树
数据结构·算法