1)内存模型
Linux 中的程序的内存分布:
Linux下32位环境的用户空间内存分布情况:
为什么需要分区?
之所以分成这么多个区域,主要基于以下考虑:
- 一个进程在运行过程中,代码是根据流程依次执行的,只需要访问一次,当然跳转和递归有可能使代码执行多次,而数据一般都需要访问多次,因此单独开辟空间以方便访问和节约空间。
- 临时数据及需要再次使用的代码在运行时放入栈区中,生命周期短。
- 全局数据和静态数据有可能在整个程序执行过程中都需要访问,因此单独存储管理。
- 堆区由用户自由分配,以便管理。
一个由 C/C++编译的程序占用的内存(memory)分为以下几个部分:
1、程序代码区(.text):
.text 部分是编译后程序的主体,也就是程序的机器指令。
程序被操作系统加载到内存的时候,所有的可执行代码(程序代码指令、常量字符串等)都加载到代码区,这块内存在程序运行期间是不变的。
- 代码区是平行的,里面装的就是一堆指令,在程序运行期间是不能改变的。
- 函数也是代码的一部分,故函数都被放在代码区,包括main函数。
2、文字常量区(.rodata):
这是一块比较特殊的存储区,里面存放的是常量,不允许修改。
- 常量字符串就是放在这里的,程序结束后由系统释放。
- rodata:read only data
3、全局区/静态区(static):
全局变量和静态变量被分配到同一块内存中。
- 在以前的C语言中,全局变量又分为初始化的和未初始化的:
- 初始化的全局变量和静态变量在一块区域(.rwdata or .data)。
- 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss), 程序结束后由系统释放。
- 在 C++中,已经不再严格区分bss和data了,它们共享一块内存区域。
4、堆区(heap):
一般由程序员分配释放(new/malloc/calloc delete/free)。
- 如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
- 注意:它与数据结构中的堆是两回事,但分配方式倒类似于链表。
5、栈区(stack):
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。
- 由编译器自动分配释放,存放函数的参数值,局部变量的值等。
- 其操作方式类似于数据结构中的栈。
- 栈区在程序运行期间是可以随时修改的。
- 每个线程都有自己专属的栈。
- 栈的最大尺寸固定,超出则引起栈溢出。
- 栈不会很大,一般都是以K为单位。
*C程序执行时的内存分配情况
下面通过一段简单的代码来查看C程序执行时的内存分配情况:
int a = 0; //a在全局已初始化数据区 char *p1; //p1在BSS区(未初始化全局变量) main() { int b; //b在栈区 char s[] = "abc"; //s为数组变量,