Linux下C程序的内存布局

Posted Shemesz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux下C程序的内存布局相关的知识,希望对你有一定的参考价值。

进程空间内的内存布局

  在Linux下,进程内存管理的对象都是虚拟内存,每个进程先天就有0~4个G的各自互不干涉的虚拟内存空间,0 ~3G都是用户空间执行自己代码,高1GB的空间是内核空间执行Linux系统调用的,这里存放在整个内核的代码和所有的内核模块,用户看到和接触到的都是该虚拟地址,并不是实际的物理内存地址。 Linux下一个进程在内存里有三部分的数据,就是“代码段”、“堆栈段”和“数据段“。其实学过汇编语言的人一定知道,一般的CPU都有上述的三种寄存器,以方便操作系统的运行。这三部分是构成一个完整执行序列的必要的部分。
在这里插入图片描述

内存分布功能
System Space这段高地址内存大小为1GB,固定留给内核用,称之为内核空间
命令行参数区在Linux操作系统中,我们编写的程序需要我们从命令行传入参数进行操作时,写入的命令行参数就存储在这片区域
栈区(Stack)参数值、局部变量(自动分配,在程序的{}内有效,离开{}自动释放)栈中的数据如果不初始化,即默认随机值,地址空间是下降(由上而下)存储
堆区(Heap)malloc分配的内存(动态申请,用完free,否则造成内存泄漏)地址空间是上升(自下而上)存储
未初始化全局数据(.bss)未初始化的全局变量或static变量
已初始化全局数据(.data)以初始化的全局变量或ststic变量
文字常量区(.rodata)const、#define、“string”等定义的数据常量(ro = read only 这段内存空间数据受系统保护为只读,如果尝试更改则会出现Segmentation Fault)
代码段编译出来的可执行文件的二进制代码;正文段虽然可以共享 ,但常常是只读的,以防止程序由于意外而修改其自身的执行。

下面我们就通过代码来看本质

#include <stdio.h>
#include <stdlib.h>
int g_var1; // g_var1是未初始化的全局变量,存放在数据段的BSS区,其值默认为0;
int g_var2=20; // g_var1是初始化了的全局变量,存放在数据段的DATA区,其值为初始化值20;
int main(int argc, char **argv) //argv里存放的是命令行参数,他存放在命令行参数区
{
    static int s_var1; // s_var1是未初始化的静态变量,存放在数据段的BSS区,其值默认为0;
    static int s_var2=10; // g_var1是初始化了的静态变量,存放在数据段的DATA区,其值为初始化值10;
    char *str="Hello"; // str是初始化了的局部变量,存放在栈(STACK)中,其值是"Hello"这个字符串常量存在DATA段里RODATA区中的地址
    char *ptr1; // ptr是未初始化了的局部变量,存放在栈(STACK)中;其值为随机值,这时候的ptr称 为“野指针(为初始化的指针)”
    char *ptr2;
    ptr1 = malloc(100); // malloc()会从堆(HEAP)中分配100个字节的内存空间,并将该内存空间的首地址返回给ptr存 放;
    ptr2 = malloc(100);
    printf("[cmd args]: argv address: %p\\n", argv);
    printf("\\n");
    printf("[ Stack]: ptr1 address: %p\\n", &ptr1);
    printf("[ Stack]: ptr2 address: %p\\n", &ptr2);
    printf("\\n");
    printf("[ Heap ]: ptr2 malloc address: %p\\n", ptr2);
    printf("[ Heap ]: ptr1 malloc address: %p\\n", ptr1);
    printf("\\n");
    printf("[ bss ]: s_var1 address: %p value: %d\\n", &s_var1, s_var1);
    printf("[ bss ]: g_var1 address: %p value: %d\\n", &g_var1, g_var1);
    printf("[ data ]: s_var2 address: %p value: %d\\n", &s_var2, s_var2);
    printf("[ data ]: g_var2 address: %p value: %d\\n", &g_var2, g_var2);
    printf("[rodata]: \\"%s\\" address: %p \\n", str, str);
    printf("\\n");
    printf("[ text ]: main() address: %p\\n", main);
    printf("\\n");
    return 0;
}

结果分析
在这里插入图片描述

以上是关于Linux下C程序的内存布局的主要内容,如果未能解决你的问题,请参考以下文章

Linux下C程序的存储空间布局

Linux下C程序的存储空间布局

linux下进程内存布局及变量存储位置检查

Linux进程虚拟内存空间布局/ Linux 下虚拟内存的分布

c程序代码的内存布局(学好C的基础)

如何在运行时查看我的 C 程序的内存布局?