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

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

相关推荐
懒惰的bit2 小时前
基础网络安全知识
学习·web安全·1024程序员节
李元豪3 小时前
【智鹿空间】c++实现了一个简单的链表数据结构 MyList,其中包含基本的 Get 和 Modify 操作,
数据结构·c++·链表
我不是星海3 小时前
1.集合体系补充(1)
java·数据结构
Natural_yz5 小时前
大数据学习09之Hive基础
大数据·hive·学习
龙中舞王5 小时前
Unity学习笔记(2):场景绘制
笔记·学习·unity
Natural_yz5 小时前
大数据学习10之Hive高级
大数据·hive·学习
love_and_hope6 小时前
Pytorch学习--神经网络--完整的模型训练套路
人工智能·pytorch·python·深度学习·神经网络·学习
夜雨星辰4876 小时前
Android Studio 学习——整体框架和概念
android·学习·android studio
奔跑的花短裤6 小时前
少儿编程启蒙学习
学习·青少年编程·机器人·ai编程
VertexGeek7 小时前
Rust学习(一):初识Rust和Rust环境配置
开发语言·学习·rust