“固定在下,动态在上”:
代码、常量这些固定不变的东西放在最下面(低地址)。
运行时动态变化的数据(堆、栈)放在上面。
“堆向上,栈向下”:
为什么堆向上? 堆是自由空间,像野草一样“生长”,自然向上。
为什么栈向下? 这是设计上的巧思。让堆和栈相对生长,可以最大化地利用它们之间的空闲内存。如果它们生长方向相同,很容易就撞到一起。
“读写属性”:
低地址的.text和.rodata是只读的,任何修改它们的企图都会导致程序崩溃(段错误)。这是重要的安全保护。
.data和.bss是可读写的。
从底向上想:.text -> .rodata -> .data -> .bss -> heap -> stack -> 参数环境。
抓住两头:最下面是只读的代码,最上面是启动参数。
分清方向:中间的堆(Heap) 像气球一样向上飘;栈(Stack) 像钉子一样向下扎。它们俩面对面,共用中间的空地。
“只读代码”就是我们编写的代码经过编译后生成的机器指令。
你写的代码:比如你写了一个C程序 printf("Hello World");
编译后:这个C语句会被编译器翻译成一系列的机器指令(比如x86或ARM的CPU能直接理解的二进制代码)。
存储位置:这些机器指令就被存放在内存的 .text 段 中。
启动参数 指的是在程序启动时,从外部传递给它的信息。它主要包含两部分:
1. 命令行参数 (argv)
这就是你在终端运行程序时,跟在程序名后面的那些参数。
在这个例子中,以下信息会作为“命令行参数”被放入高地址的内存区域:
argv[0]: "./my_program" (程序名本身)
argv[1]: "-o"
argv[2]: "output.txt"
argv[3]: "file1.txt"
argv[4]: "file2.txt"
在你的C语言的 main 函数中,就是通过 int main(int argc, char *argv[]) 来获取这些参数的。
2. 环境变量 (envp)
环境变量是系统级或用户级的全局配置信息,任何程序都可以访问。
常见的环境变量:
PATH:系统查找命令的路径。
HOME:当前用户的家目录。
USER:当前用户名。
你的程序也可以读取这些变量来了解自己运行的环境。
低地址的“只读代码”:是程序本身,是固定的“身体”,负责执行逻辑。
高地址的“启动参数”:是每次启动时的“上下文”或“输入”,是动态变化的,告诉程序这次运行具体要做什么、在什么环境下做。