[应用相关]

(转)C 程序的内存空间布局

[复制链接]
417|1
手机看帖
扫描二维码
随时随地手机跟帖
heimaojingzhang|  楼主 | 2018-8-18 14:07 | 显示全部楼层 |阅读模式
本帖最后由 heimaojingzhang 于 2018-8-18 14:09 编辑

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. 命令行参数和环境变量

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

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

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

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

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

CPU 执行的机器指令
父进程和子进程之间可共享正文段
存在于程序镜像文件中且只读, 由 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" 优化成一块
}

文件映射区

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

内核映射区

操作系统的内核程序映射到这个区域
keaibukelian| | 2018-8-18 15:03 | 显示全部楼层
我只有在报错的时候才会想了解一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

74

主题

3832

帖子

4

粉丝