1、内存分布
linux进程中的内存分布_linux下的内存分布_土豆西瓜大芝麻的博客-CSDN博客
BSS段:存放未初始化的全局变量(包括静态局部变量、静态全局)和初始化为0的全局变量(包括静态局部变量、静态全局),属于静态分配内存
Data段: 数据段,用来存放已经初始化且初始化值为非零的全局变量(包括静态变量)
代码段:通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
栈(stack):栈又称堆栈,是用户存放程序临时创建的局部变量(不包括静态局部变量。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。
字符常量区(rdata):该区域存放的是字符常量,属于只读区域,有些教材把这个区域归位代码段
全局的未初始化变量存在于.bss段中,具体体现为一个占位符;全局的已初始化变量存于.data段中;而函数内的自动变量都在栈上分配空间。.bss是不占用可执行文件空间的,其内容由操作系统初始化(清零);而.data却需要占用,其内容由程序初始化,因此同一个全局变量是否赋初值将导致可执行文件的大小发生改变。
bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
data(已手动初始化的数据)段则为数据分配空间,数据保存在目标文件中。 数据段包含经过初始化的全局变量以及它们的值。BSS段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在数据段后面。当这个内存区进入程序的地址空间后全部清零。包含数据段和BSS段的整个区段此时通常称为数据区。
“.rodata”段存放的是只读数据,一般是程序里面的只读变量(如const修饰的变量)和字符串常量。单独设立“.rodata”段有很多好处,不光是在语义上支持了C++的const关键字,而且操作系统在加载的时候可以将“.rodata”段的属性映射成只读,这样对于这个段的任何修改操作都会作为非法操作处理,保证了程序的安全性。另外在某些嵌入式平台下,有些存储区域是采用只读存储器的,如ROM,这样将“.rodata”段放在该存储区域中就可以保证程序访问存储器的正确性。
另外值得一提的是,有时候编译器会把字符串常量放到“.data”段,而不会单独放在“.rodata”段。有兴趣的读者可以试着把SimpleSection.c的文件名改成SimpleSection.cpp,然后用各种MSVC编译器编译一下看看字符串常量的存放情况。
变量类型 | 初始条件 | 所处数据段 | 解释 | 代码样例 |
局部变量 | —— | 栈空间 | 无论是否初始化,是否有const修饰,都是在栈空间 | |
静态局部变量 | 初始0 | BSS | 初始为0会按未初始化处理,在comm段 | |
静态局部变量 | 初始非0 | DATA | ||
全局变量 | 初始0 | BSS | 初始为0会按未初始化处理,在BSS段 | |
全局变量 | 初始非0 | DATA | ||
const全局变量 | —— | const段 | 不论是否初始化都在const段,且const段占用可执行文件大小 | |
const静态变量 | const段 | 不论是否初始化都在const段,且const段占用可执行文件大小 | ||
全局字符串常量 静态字符串常量 | char *str = “hello” | 指针存在data段,“hello”在字符串常量段 | ||
全局字符数组 静态字符数组 | char str[] = "world" | Data | ||
局部字符串常量 | char *str = “hello” | 指针在栈中,“hello”在字符串常量段 | ||
局部字符串数组 | char str[] = "world" | 栈 |