文章目录
- 1.bss段
- 2.data段
- 3.rodata段
- 4.text段
- 5.stack段
- 6.heap段
1.bss段
该段用来存放没有被初始化或初始化为0的全局变量,因为是全局变量,所以在程序运行的整个生命周期内都存在于内存中。
有趣的是这个段中的变量只占用程序运行时的内存空间,而不占用程序文件的储存空间。
- 可以用以下程序来说明这点,文件名为bss.c
#include <stdio.h> int bss_data[1024 * 1024]; int main()
{ return 0;
}
这个程序非常简单,定义一个4M的全局变量,然后返回。编译成可执行文件bss,并查看可执行文件的文件属性如图2所示:
从可执行文件的大小4774B可以看出,bss数据段(4M)并不占用程序文件的储存空间。
在下面的data段中,我们可以看到data段的数据是占用可执行文件的储存空间的。
2.data段
初始化过的全局变量数据段,该段用来保存初始化了的非0的全局变量,如果全局变量初始化为0,则编译有时会出于优化的考虑,将其放在bss段中。因为也是全局变量,所以在程序运行的整个生命周期内都存在于内存中。
与bss段不同的是,data段中的变量既占程序运行时的内存空间,也占程序文件的储存空间。
- 可以用下面的程序来说明,文件名为data.c:
#include <stdio.h> int data_data[1024 * 1024] = {1}; int main()
{ return 0;
}
这个程序与上面的bss唯一的不同就是全局变量int型数组data_data,其中第0个元素的值初始化为1,其他元素的值初始化成默认的0,而因为数组的地址是连续的,所以只要有一个元素在data段中,则其他的元素也必然在data段中。
编译链接成可执行文件data,并查看可执行文件的文件属性如图3所示:
- 从可执行文件的大小来看,data段数据(data_data数组的大小,4M)占用程序文件的储存空间。
3.rodata段
该段是常量数据段,用于存放常量数据,ro就是Read Only之意。但是注意并不是所有的常量都是放在常量数据段的,其特殊情况如下:
- 1)有些立即数与指令编译在一起直接放在代码段(text段,下面会讲到)中。
- 2)对于字符串常量,编译器会去掉重复的常量,让程序的每个字符串常量只有一份。
- 3)有些系统中rodata段是多个进程共享的,目的是为了提高空间的利用率。
4.text段
text段就是代码段,用来存放程序的代码(如函数)和部分整数常量。
它与rodata段的主要不同是,text段是可以执行的,而且不被不同的进程共享。
5.stack段
该段就是栈段,用来保存临时变量和函数参数。
程序中的函数调用就是以栈的方式来实现的,通常栈是向下(即向低地址)增长的,当向栈中push一个元素,栈顶指针就会向低地址移动,当从栈中pop一个元素,栈顶指针就会向高地址移动。
栈中的数据只在当前函数或下一层函数中有效,当函数返回时,这些数据自动被释放,如果继续对这些数据进行访问,将发生未知的错误。通常我们在程序中定义的不是用malloc系统函数或new出来的变量,都是存放在栈中的。
例如,如下函数:
void func()
{ int a = 0; int *n_ptr = malloc(sizeof(int)); char *c_ptr = new char;
}
整型变量a,整型指针变量n_ptr和char型指针变量c_ptr,都存放在栈段中,而n_ptr和c_ptr指向的变量,由于是malloc或new出来的,所以存放在堆中。当函数func返回时,a、n_ptr、c_ptr都会被释放,但是n_ptr和c_ptr指向的内存却不会释放。
因为它们是存在于堆中的数据。
6.heap段
heap(堆)是最自由的一种内存,它完全由程序来负责内存的管理,包括什么时候申请,什么时候释放,而且对它的使用也没有什么大小的限制。
在C/C++中,用alloc系统函数和new申请的内存都存在于heap段中。
- 参考:程序运行时内存的各种数据段