前言
在刷ROP题的时候涉及到将字符串写入内存的问题,学习过程中需要更加细致的了解一些概念,简单的记录一下自己的理解。
内存区域
简单的了解一下内存中的一些区域:
栈(stack):由编译器自动分配及释放,存放着函数的参数值、局部变量的值等。
堆(heap):一般是由程序员通过相应的函数分配和释放,若程序员不释放,程序结束可能由OS回收。
全局区(静态区,static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(.data段,data segment),未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(.bss段,bss segment)。程序结束后由系统释放。
文字常量区:存放文字等不可修改的常量,由系统分配和释放。
程序代码区:存放程序编译连接后生成的二进制机器码指令。
下面是一个例子了解这些区域:
1 |
|
关于这些内存区域的一些说明:
全局初始化区与全局(静态)初始化区是在同一段内存连续分配的,按内存地址增长方向分配
全局初始化区与全局未初始化区不在同一段内存区
栈空间也是同一段内存连续分配的,按内存地址减小方向分配
堆空间也是同一段内存连续分配的,按内存地址增大方向分配
文字常量区在自己特有的内存段内,且有机制控制字符常量不被修改(当字符串相同的时候,系统有时还会将两个指针指向同一处)
在文字常量区的字符串不可以被修改,而在内存堆空间的字符串可以被修改
bss段和data段
bss段(Block Started by Symbol segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域,一般在初始化时bss 段部分将会清零(bss段属于静态内存分配,即程序一开始就将其清零了)。比如,在C程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss段中。
text(二进制机器代码段)和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;而bss段不在可执行文件中(不占用exe的空间,只标记空间大小),由系统初始化。
看一下这样两个程序:
1 |
|
1 |
|
当我们编译完这两个程序之后查看编译好的文件大小会发现程序2比程序1要大。原因在于程序1的变量位于.bss段,而程序2的变量位于.data段。
全局的未初始化变量存在于.bss段中,具体体现为一个占位符;全局的已初始化变量存于.data段中;而函数内的自动变量都在栈上分配空间。
.bss是不占用.exe文件空间的,其内容由操作系统初始化(清零);而.data却需要占用,其内容由程序初始化,因此造成了上述情况。
还有一些点需要注意:
.bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小
.data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中
.data段包含经过初始化的全局变量以及它们的值
.bss段的大小从可执行文件中得到,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含DATA和BSS段的整个区段此时通常称为数据区
总结
下面的图可以很好的理解和总结这些概念之间的关系: