[Rust](笔记) 程序内存布局
内存布局
+------------------+  高地址
|      Stack       |  (栈:局部变量、函数调用信息等)
|        ↓         |   - 函数内的局部变量(例如基本类型、结构体等)
|                  |   - 动态分配的类型的元数据(例如 `String` 的指针、长度、容量)
+------------------+
|        ↑         |
|       Heap       |  (堆:动态分配的内存,通常通过 Box、Vec、String 等分配)
|                  |   - `Box::new`、`Vec::new`、`String::from` 创建的内容
|                  |   - 对象的数据存储位置
+------------------+
|       BSS        |  (未初始化的静态/全局变量)
|                  |   - `static mut COUNT: u32;` 等未初始化的变量
+------------------+
|      Data        |  (已初始化的静态/全局变量)
|                  |   - `static NUMBERS: [i32; 3] = [1, 2, 3];` 等初始化的变量
+------------------+
|     .rodata      |  (只读数据段:常量、字符串字面量等)
|                  |   - 字符串字面量 `let s = "hello";`
|                  |   - `const SIZE: u16 = 1024;`
+------------------+
|      Text        |  (代码段:存放编译后的机器码)
|                  |   - 函数的机器码
|                  |   - 程序执行的指令
+------------------+  低地址
- 只读数据段 .rodata和 已初始化数据段Data中的静态/全局变量有时候会交叉,因为它们都是程序中“静态”部分的一部分。不同的编译器和操作系统对这两个区域的划分可能有所不同。
- 栈和堆是动态变化的,而其他如数据段、只读数据段等通常是静态的,在程序运行时不会改变。
内存地址与指针
| 类型 | 定义 | 特点 | 使用场景 | Rust示例 | 
|---|---|---|---|---|
| 内存地址 | 内存中具体位置的数值标识 | 只读、基础(仅为地址,不可操作) | 低级编程(通过指针间接使用) | 如 0x7ffd5d8e3a40Rust中不直接使用,通常通过指针间接访问。 | 
| 指针 | 存储内存地址的变量 | 有类型、可以操作所指向的内存,Rust有安全检查 | 内存引用、间接访问内存 | let ptr: *const i32 = &x(裸指针示例,需在unsafe块内使用) | 
| 裸指针 | 不安全的原始指针(即直接操作内存的指针) | 无安全检查,允许可变或不可变操作 | 底层系统编程、FFI等 | let raw_ptr = &value as *const i32(unsafe块中使用) | 
| 胖指针 | 包含地址和额外元数据(如长度) | 存储额外信息(如切片的长度或类型信息),更复杂 | 切片、动态大小类型 | &[i32]、&str、*const [i32](切片、动态大小类型的示例) | 
备注:
- 内存地址:Rust中一般不会直接使用内存地址,而是通过指针来间接引用。实际使用时,指针的地址值是通过指针类型表示的。
- 指针:指针分为可变指针(&mut T)和不可变指针(&T)。unsafe代码中也有裸指针(*const T和*mut T)可用于底层操作。
- 裸指针:裸指针不受Rust的所有权和借用检查系统的保护,因此在使用时需要特别小心,通常需要在unsafe块中使用。
- 胖指针:常用于处理动态大小类型(DST),如切片(&[T])、字符串切片(&str)和trait对象(dyn Trait)等。
栈与堆的小记
栈内存从高位地址向下增长,且栈内存是连续分配的,一般来说操作系统对栈内存的大小都有限制,因此 C 语言中无法创建任意长度的数组。在 Rust 中,main 线程的栈大小是 8MB,普通线程是 2MB,在函数调用时会在其中创建一个临时栈空间,调用结束后 Rust 会让这个栈空间里的对象自动进入 Drop 流程,最后栈顶指针自动移动到上一个调用栈顶,无需程序员手动干预,因而栈内存申请和释放是非常高效的。
与栈相反,堆上内存则是从低位地址向上增长,堆内存通常只受物理内存限制,而且通常是不连续的,因此从性能的角度看,栈往往比堆更高。
    为之则易,不为则难。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号