C 程序的内存空间布局

本文详细介绍了C程序的内存空间布局,包括命令行参数和环境变量、栈、堆、bss段、data段和text段。栈存储自动变量和函数信息,堆用于动态分配,bss段存放未初始化的全局变量,data段则包含初始化的全局变量。文本段包含机器指令,常量可能存在于不同的内存区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C 程序的内存空间布局

表格中, 从上到下为高地址到低地址方向

segment含义
argument and environment命令行参数和环境变量(环境表和环境字符串)
stack
heap
bss未初始化数据段
data初始化数据段
text正文段

1. 自由存储区: C++中, 堆是由 new 和 delete 管理的, 自由存储区(free store)是由 malloc 和 free 管理的
2. 全局区: C++中, 使用全局区(静态区)存储全局变量和静态变量, 不再区分data和bss, 即初始化和未初始化的数据占用同一块内存
3. 常量区: 存储字符串常量, 正常手段不允许修改, 和上面表格中的地址不连续存放, 所以单独说?
4. 立即数: 对于整数类型, 如果初始化常量值出现在表达式语句中, 通常会成为立即数, 被包含在生成的代码中, 即数字常量占用代码段汇编指令的操作数部分?
5. 全局区的初始化常量值: 没有参与代码生成的常量,比如用于全局变量的初始化、数组声明、模板参数等等,哪里也不存,在编译期就处理了

1. 命令行参数和环境变量

  1. 使程序了解进程环境,在执行时分配内存
  2. 在 shell 中执行某个程序(shell 的子进程)时,shell 进程调用 exec 函数将命令行参数传递给要执行的程序

2. 栈

  1. 存储自动变量, 函数调用者信息, 包括函数参数(可变参数列表的压栈方向是从右向左), 函数内局部变量, 函数返回值, 函数调用时的返回地址
  2. 执行流执行到函数调用时分配内存, 高地址是栈底, 向低地址方向增长
  3. 函数返回时, 系统自动回收内存

3. 堆

  1. 用于动态分配的内存, 需要手动管理内存
  2. 执行流执行到手动分配内存函数调用(如 malloc 或 new)时, 分配内存

4. bss 段

  1. Block Started by Symbol, 即以符号开始的内存块
  2. 未初始化的数据可能是全局变量, 静态变量
  3. bss 段并不占用可执行程序的镜像的空间,而是在执行时分配内存,并由 exec 函数初始化为0, 例如声明全局数组 int array[100], 不会将100个0记录在可执行文件镜像中,而只是记录了标识符a和其所占用的内存大小
  4. 变量的大小记录在符号表中,要分配的整个 bss 段的大小记录在段表(Section headers)中

5. data 段

  1. 具有明确初始值的全局变量和静态变量
  2. 存在于程序镜像文件中,由 exec 函数从程序镜像文件中读入内存

6. text 段

  1. CPU 执行的机器指令
  2. 父进程和子进程之间可共享正文段
  3. 存在于程序镜像文件中且只读, 由 exec 函数从程序镜像文件中读入内存, 例如在 shell 中正在执行的程序运行正文段的指令

举例

int a = 0;      // a 在 data
char *p1;       // p1 在 bss

main()
{
    int b;                      // b 在 stack
    char s[] = "abc";           // s 在 stack, abc\0 在常量区
    char *p2;                   // p2 在 stack
    char *p3 = "123456";        // p3 在 stack, 123456\0 在常量区
    static int c = 0;           // c 在 data
    p1 = (char *)malloc(10);    // 申请的10字节内存在 heap, bss中的指针指向heap中的内存
    p2 = (char *)malloc(20);    // 申请的20字节内存在 heap, stack中的指针指向heap中的内存
    strcpy(p1, "123456");       // 123456\0 在常量区,编译器可能会将它与 p3 所指向的 "123456" 优化成一块
}

文件映射区

进程将文件从硬盘读取到文件映射区,以后在内存操作文件

内核映射区

操作系统的内核程序映射到这个区域

参考

  1. readelf命令
  2. 面试官问我:bss段的大小记录在哪里?
  3. 内存区划分、内存分配、常量存储区、堆、栈、自由存储区、全局区
  4. 常量存在内存中的那里?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值