内存管理和内存分配是操作系统需要重点考虑的问题。以下简单的的写下内存相关的知识。
内存主要分为五个区域:静态区(.data段、.bss段)、文字常量区、代码区(.text)、堆(.heap)、栈(.stack)。
在实际编程中,要时刻注意变量所在的内存区域,以及其生命周期,避免出现内存错误问题。
1. 数据段-.data
数据段属于静态分配内存
——有初值的全局变量、static变量
2. bss段
未初始化的全局变量,或者初始化为0的全局变量,此区域在程序载入时候由内核清0.属于静态分配内存
——未初始化的全局变量
3. 代码段.text
text段在内存中被映射为只读
——可执行代码,字符串常量
4. heap段
动态分配的内存,保存程序的动态变量,堆是先进先出FIFO。
——由malloc、calloc、realloc等函数,手动分配的内存空间
注意:malloc申请的内存不负责初始化,而calloc申请的内存已经初始化为0. realloc可以扩充之前申请的内存。
堆的地址空间向上生长,即堆上保存的数据越多,堆的地址就越高。
5. stack段
栈保存函数的局部变量,参数,以及返回值。是一种后进先出的数据结构。最后放到栈上的数据,将会是最先从栈上移走的数据。
——局部变量、参数、返回值。
栈的生长方向为向下生长,当栈上保存的数据越多,栈的地址就越低。
PS:从存储区域来看:
——寄存器: 速度最快,由编译器来分配。
——堆栈: 堆栈就是栈(stack)。是一种特别快、特别有效的数据保存方式,仅次于寄存器。
——堆: 手动分配固定大小的内存区域,编译器不知道其生命周期和空间大小,更灵活。但是分配存储空间会花掉时间。
从存储方式来看:
——静态存储:数据存活于整个程序的生命周期。全局变量以及static数据
——常量存储:常数值通常置于程序代码内部。这样是十分安全的,因为text段是只读的,所以永远也不会改变。有需要保护的常数,可以将其通过const来修饰。
那么,linux下的虚拟地址空间如何分布?
——只读段: 代码段、rodata段(常量字符串,#define定义的常量)
——数据段: 保存全局变量、静态变量的空间
——堆 : 动态内存,通过malloc、calloc、realloc、new等来分配的内存。堆顶的位置可以通过brk和sbrk进行动态调整
——文件映射区域: 动态库、共享内存等映射物理空间的内存。mmap等函数所分配的虚拟地址空间
——栈 : 用于维护函数调用上下文空间、一般为8M, 可以通过 ulimit -s 查看。
——内核虚拟空间:用户不可见的内存区域,由内核管理(页表存放在内核空间)
参看此链接文章——linux环境内存分配原理 mallocinfo
由于虚拟内存的存在,系统整理内存称为可能。即使系统内存整理调整后,虚拟内存的地址不会变,各个线程的栈内存也应该不会发生变化,只是每个内存页对应的物理内存发生变化。
网友评论