1. C程序的内存空间布局解析
在Linux系统编程中,理解C程序的内存空间布局是基础中的基础。让我们先来看一张典型的内存布局图:

这个布局展示了32位Linux系统中进程的虚拟地址空间分配。从上到下分别是:
- 栈(Stack):向下增长,存储局部变量、函数参数和返回地址
- 堆(Heap):向上增长,用于动态内存分配(malloc/free)
- 未初始化数据段(BSS):存储未初始化的全局变量
- 已初始化数据段(Data):存储已初始化的全局变量和静态变量
- 代码段(Text):存储程序的可执行指令
注意:当堆和栈空间不足时,它们会分别向上和向下扩展,挤压中间的区域。这个中间区域通常用于存放共享库(静态库/动态库)的映射。
1.1 32位系统的4GB内存限制原理
32位系统的虚拟地址由32位二进制数组成,这意味着:
- 可寻址范围:0 ~ 2³²-1(即0x00000000到0xFFFFFFFF)
- 每个地址对应1字节,因此总容量为4GB(4,294,967,296字节)
这个限制源于CPU的地址总线宽度。32位CPU最多只能用32位来标记内存地址,所以虚拟地址空间的上限就是4GB,与实际物理内存大小无关。
1.2 用户态程序从0x08048000开始的奥秘
在Linux i386架构下,ELF可执行文件默认加载到0x08048000,主要原因有三:
-
低地址空间预留:
- 0x00000000~0x08047FFF区域被刻意保留
- NULL指针指向0x0,访问会触发段错误(方便调试)
- 用于加载动态链接器(ld-linux.so)等系统组件
-
历史兼容性与对齐要求:
- 0x08048000是4KB页对齐地址(0x1000 × 0x8048)
- 避免与动态链接器、库文件的加载区域冲突
-
虚拟地址空间划分:
- 经典3G/1G划分:
- 用户态:0x00000000~0xBFFFFFFF(3GB)
- 内
- 经典3G/1G划分:
