C程序运行时的内存分布

时间:2023-02-23 16:40:07
C程序运行时的内存分布

该篇博客是自己学习的总结,如果有哪里理解的不对的地方,希望大家可以指点。

一、C内存空间分布图

C程序运行时的内存分布

二、各内存区域详解

1.代码区(.text): 该区域主要存放二进制可执行文件。

2.数据区(.data): 数据区可详细分为三块区域,分别是只读数据区、初始化数据区、未初始化数据区。

1). 只读数据区(.ordata) : 顾名思义,这个区域存放的是一些常量,包括字符串常量、const修饰的全局变量;

注意一: 字符串常量都是存储在只读数据区的。看下面一个例子,

 #include <stdio.h>

 int main(void)
{
char str[] = "I Love CHINA"; printf("the address of array: %p\n", str);
printg("the address of string: %p\n", "I Love CHINA"); str[] = 'W';
printf("%s\n", str); return ;
}

调试结构为:

the address of array: 0xbfa5052f
the address of string: 0x80485f5
W Love CHINA

看到这里可能就迷糊了,上面不是说字符串常量都存放在只读数据区吗?其实原因是这样的,当我们用字符串初始化字符数组时,是先将字符串字面量存储在只读数据区,当调用该初始化所在函数时,会将在数据区的数据拷贝一份到当前数组,当前运行的程序中就有两个''I Love CHINA'';我们改变了的其实是赋值到字符数组str所对应的在栈中的空间的值,而存放在数据区的字符串常量并没有改变。

注意二: 而const修饰的局部变量还是像普通的局部变量一样存放在栈中,只是不能显式的改变该变量。

2). 初始化数据区(.rwdata): 该区域用来存放初始化不为0的全局变量和static修饰的局部变量。

3). 未初始化数据区(.bss): 与初始化数据区类似,但是它存放的是初始化为0、未初始化的全局变量和static修饰的局部变量。这样做的目的主要是为了减少可执行二进制文件占用的存储空间,特别是在一些嵌入式设备中显得尤其重要。如下图,

 #include <stdio.h>

 int arr[] = {};

 int main(void)
{
printf("hello world\n"); return ;
}

C程序运行时的内存分布

 #include <stdio.h>

 int arr[] = {};

 int main(void)
{
printf("hello world\n"); return ;
}

C程序运行时的内存分布

3. 栈: 栈存放的是程序中的局部变量,  当然函数形参、返回值也都存储在栈中。栈是由系统自动管理,变量的出栈入栈操作都由系统通过移动栈顶指针来完成来完成,并不是真正的清除变量,所以当我们使用局部变量之前一定要给它赋值,否则就是一个不确定的值。

4.堆: 堆空间解决了自动分配不灵活,对内存造成浪费等问题。可以通过malloc函数申请所需大小的空间,注意这块空间申请了之后会一直存在,所以一定要和free一起使用,等用完之后马上释放,否则会造成内存泄漏,严重会导致程序停止运行。我们使用mallco函数带来方便灵活的同时,也带来了内存碎片的问题,所以当要求程序长时间运行时,必不可免的就要解决malloc带来的内存碎片问题。