目的

写着一篇的目的主要是看到虚拟内存的struct等过多,看了下面忘了上面的,所以记录一下,之前章节的可能会补充

内存分配

静态分配

在编译期由编译器完成,已经知道了当前变量所占大小,分配一块固定的内存存储起来

动态分配

应用有一块可以动态增减的内存空间-堆,需要对这一块堆进行管理,如果堆的大小固定,则为连续内存分配问题。有一个概念,内存碎片,指的是无法分配和使用的内存空间,进一步细分有:

  • 内碎片:已经被分配出去,但是占有的应用不使用这块区域,操作系统无法利用这块区域
  • 外碎片:没被分配出去,但是太小了以至于无法分配给其他应用

经典的C语言中有动态分配的函数,malloc以及free,这两个函数用于动态分配或者释放内存。相比较静态分配,由于动态分配有一个连续内存分配算法,所以会有一些额外的开销。

Rust中的堆

  • 裸指针 *const T/*mut T 与C中的普通指针基本相等
  • 引用&T/&mut T 实际上是一个地址范围(还不清楚为啥)

Rust中与动态内存分配相关的智能指针:

  • Box<T>在创建时会在堆上分配一个类型为T的变量,当Box<T>回收时,指向的变量也会被回收
  • Rc<T>为单线程上使用的引用奇数类型, 同时可以有多个智能指针指向同一个堆上变量Rc<T>, 堆上另外一个位置存储了这个变量目前引用的次数N, 如果N的数量变为0, 则会被回收
  • RefCell<T> , 与Box等智能指针不同的是, 如果违反借用规则, 会在运行时panic退出, 它可以在自身不可变的情况下修改内部的值
  • Mutex<T> 为互斥锁,在多线程中使用, 能避免数据竞争, 它时常与Arc<T>一起使用

还有一些其他的:

  • 向量Vec<T>
  • 键值对容器BTreeMap<K,V>
  • 有序集合BTreeSet<T>
  • 链表LinkedList<T>
  • 双端队列VecDeque<T>
  • 变长字符串String

图示:

image-20220505105723816