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程序的内存布局的主要内容,如果未能解决你的问题,请参考以下文章