一、可执行程序内存分配
1、可执行程序内存分段
一个可执行程序脚本可以分为3个基本段,代码段,数据段,bss段;unix下可以使用size命令查看可执行文件的段大小信息,size a.out
header->代码text->数据data->bss
- 1、bss(block started by symbol),通常是用来存放程序中未初始化的全局变量和静态变量的存储区域
- 可读写,在程序执行之前bss段会自动请0,所以为初始化去的全局变量的静态变量在程序执行之前已经为0了。数据段存放的是初始化后的全局变量和静态变量;
- 2、数据段.data 存放编译阶段就能确定的数据,可读写
- 就是静态存储区,赋初值的全局变量、静态变量以及常量存放在此;
- 3、代码段.text 代码段通常指用来存放执行d代码的一块存储区域
- 该区域大小在程序运行前就以确定,通常是只读,某些架构也与允许修改程序
- 也可能包含一些只读的常数变量,如字符串常量等
2、五大内存分区
- 1、栈区(堆栈区stack)
由编译器自动分配释放,存放函数的参数和局部变量的值,类似于数据结构中的栈; - 2、堆(heap)
由程序员自动分配和释放,若没有释放,最后程序结束后由OS回收;
与数据结构在中的堆不一样,分配方式类似于链表,使用malloc或new申请;
当系统收到程序申请时,会遍历记录空闲内存地址的链表,寻求找到一个大于申请空间的堆节点,将该节点删除,并将该节点的空间分配给程序;新申请的内存块的首地址中记录本次分配内存块的大小,在释放时可以正确释放掉该空间; - 3、全局静态存储区
全局变量于静态变量的存储时放在一起的,初始化的全局变量于静态变量方在一起,未初始化的全局变量与静态变量存放在相邻的另一块区域; - 4、文字常量区
常量字符串等常量字符存储在该区域,只读存储,程序结束后由系统释放 - 5、程序代码区
存放程序的二进制代码区;
代码段、数据段、堆栈段时cpu级别概念,五大分区数据属于程序语言级别概念
3、可执行程序内存空间与逻辑地址空间映射与划分
左边为unix系统的可执行文件,右边时进程对应的逻辑地址空间的划分
二、static变量
1、静态全局变量和全局变量的区别
全局变量 | 静态全局变量 | |
---|---|---|
生命周期 | 程序运行到该变量至程序结束 | 程序开始至程序结束 |
作用域 | 所有代码 | 当前文件 |
代码段中是位置 | 全局数据区(数据段.data) | 全局数据区(数据段.data) |
2、静态局部变量和局部变量的区别
局部变量 | 静态局部变量 | |
---|---|---|
生命周期 | 函数调用到该变量至函数返回 | 程序开始至程序结束 |
作用域 | 函数内部 | 函数内部 |
代码段中是位置 | 栈 | 全局数据区(数据段.data) |
- 1、静态局部变量定义在函数内部,生存周期为整个远程序,但是只能在该函数内部使用,退出函数时,尽管改变仍存在,但是不能使用。
- 2、对于基本类型的静态局部变量若没有赋初值,系统会自动赋值为0;而其他变量不会赋初值,其值不能确定;
- 3、全局变量本身就是静态方式存储,与静态全局变量一样,作用域不同,静态全局变量仅限于当前文件,为全局变量可以使用关键字extern来使用其他文件中的全局变量;
- 4、函数每次访问静态局部变量时,该变量的值为上一次访问修改后的值;
三、static函数
- 在函数返回类型前加上关键字static即为静态函数;
- 一般函数的定义是extern的,但是静态函数只是在它声明的文件中可以访问,其他文件不能访问;
- static函数也称为内部函数,其他一般的函数为外部函数
- 静态函数在不同文件定义相同的函数名,不会发生冲突,允许不同文件定义相同的静态函数;
- 存储说明符 auto、register、extern 和static对应两种存储期:动态存储期(前三个)和静态存储期(static);
- 静态局部变量通常用来作为一个函数的计数器;
- 静态函数被分配在一个一直使用的存储区,知道结束程序,可以避免调用函数时的压栈和出栈,提高代码执行速度。