[toc]
内存处理
当一个程序(比如你编译好的 Rust 软件)被操作系统加载到 RAM 中时,它的内存从上到下其实被划分成了以下几个主要的房间:
代码区(Text / Code Segment)
装什么: 存放你写的代码编译出来的 CPU 机器指令(就是一堆 010101 的控制命令)。
特点: 只读。绝对不允许程序在运行的时候去修改自己的代码,否则就乱套了。
只读数据区(ROData Segment)
装什么: 存放编译期就完全确定的常量和字面量,比如 "hello"、"请输入您的账号:"。
特点: 既不是栈,也不是堆。它在程序启动时就分配好了,大小死死固定,直到程序关闭才释放。它也是只读的,哪怕用 C 语言的底层指针强行去改这块区域,操作系统也会立刻弹出 Segmentation fault(段错误)直接杀掉你的程序。
堆(Heap)
装什么: 存放运行期间动态申请、大小不固定的数据(如 String::from、Vec)。
特点: 空间巨大,由程序员或垃圾回收器(GC)手动申请和释放。
栈(Stack)
装什么: 存放函数的局部变量、形参,以及指向堆或只读区的指针(激光笔)。
特点: 空间小,随着函数的进出自动开辟和自动销毁,速度极快。
编译器
从“文本”到“思维”
当你按下编译按钮,前端车间开始解构你的文本代码:
词法分析: 像背单词一样,把 let mut s = "hello" 拆成 let(关键字)、mut(修饰符)、s(变量名)、=(赋值符)、"hello"(字符串)。
语法分析: 检查你的句式对不对。如果对,它会把这些单词连成一棵树,叫做 AST(抽象语法树)。这就像是把一段长篇大论变成了清晰的结构图。
检查和优化
这是编译器最强大的地方,也是它帮我们管理内存的阶段:
语义检查(类型检查): 它会盯着你的树看,确保你没有让一个整数去加一个字符串,或者像 Rust 编译器那样,检查你有没有违反借用规则。
内存与生命周期规划: 这就是你之前理解的重点! 编译器在这一步会数一数你写了多少个形如 "hello" 的字面量。它心里默默记下:“OK,这几个家伙尺寸固定,我要在只读区(.rodata)给它们留好位置。” 同时,它会计算好每个局部变量在栈上的偏移量。
代码优化: 它会砍掉你写的多余代码。比如你写了 let x = 1 + 1;,优化器会直接把它改成 let x = 2;,绝对不把无聊的加法算式留到运行时去浪费 CPU。
构建和打包
中端车间把优化好的结构图交出来后,后端车间负责针对具体的硬件进行翻译:
目标代码生成: 根据你的电脑芯片(是 Intel 的 x86 还是手机的 ARM),把结构图翻译成对应的汇编语言和最终的机器码(二进制二进制)。
打包静态资源: 默默把那几个刻在石头上的字("hello"、"bilib")塞进可执行文件的尾部,通知操作系统启动时直接送入【只读数据区】。