32位系统总的地址空间大小是2^32 = 4GB
在windows情况下,默认将高地址的2GB空间分配给内核(当然也可以分配1GB),而在Linux情况下,默认将高地址的1GB空间分配给内核,内核空间以外剩下的空间给用户使用也被称为用户空间,内核是操作系统的核心部分,负责管理计算机硬件和提供系统服务。内核通常在计算机的最高特权级别运行,控制着系统的整体操作。。
栈空间(stack):
由上图中可以知道进程地址空间中最顶部的段是栈,代码中函数调用、定义局部变量(但不包含static修饰的变量)或声明的类的实例等等都要使用栈空间,当函数执行完(也就是程序执行超过了这个函数的作用范围的时候),操作系统会把该函数在栈中存放的数据出栈,也就是函数执行完需要return的时候系统会自己释放内存。但是如果不断的向栈中压入数据,达到最大的栈空间大小的话就会栈溢出(stack overflow),这时候程序运行就会出现段错误(Segmentation Fault)。
堆空间(heap):
堆用于存储那些生存期与函数调用无关的数据,堆分配的接口通常有malloc()、calloc()、realloc()、new等,但是堆空间有一个特点就是申请空间之后如果不主动释放(free()、delete等),那么这个堆空间会依然存在,所以这种动态申请的内存需要程序员自己分配和释放。
bss段:
bss(简称:Block Started by Symbol)段(bss segment)是用来保存未被初始化的全局变量或者静态(全局)变量的内容的一块内存区域,假如你写"static int a;" 或者 " int a; " , 则a的内容就保存在bss段中。
数据段:
data数据段(data segment)和bss段都是用来保存全局变量或静态(全局)变量的内容的一块内存区域,区别在于数据段是保存已经初始化的全局变量或静态(全局)变量,假如你写"static int a = 2; " 或者 "int a = 2; " ,那么a的内容就保存在数据段中了,而且初始值为2。
rodata则是用来存放常量的一块内存区域。
代码段:
代码段(code segment/text segment)分为两个部分: text和 init。
text 用于存放整个程序中的代码。
init 用于存放系统中用来初始化启动你的程序的一段代码。
一个可执行程序至少包含:代码段 + 数据段 + BSS 段
一般情况下,一个可执行二进制程序(在 linux下为一个进程单元),在存储时(没有加载到内存运行),至少拥有三个部分,分别是代码段(text)、数据段(data)、和BSS 段。
这三个部分一起组成了可执行程序(可能还有其他的段,和平台相关)
当应用程序运行时(运行态),此时需要另外两个域:堆和栈。正在运行的程序:代码段 + 数据段 + BSS 段 + 堆 + 栈。
如图所示为可执行应用程序存储态和运行态的结构对照图。一个正在运行的 C 程序占用的内存区域分为代码段、数据段(初始化数据)、BSS 段(未初始化数据)、堆和栈 5 部分
在C语言中,局部变量和全局变量在运行过程中存储在不同的地方。
- 局部变量:
局部变量是在函数内部声明的变量,只在声明它的函数内部可见。
它们通常存储在栈上。每当函数被调用时,一个新的栈帧(stack frame)被创建,用于存储局部变量、函数参数和其他与函数调用相关的信息。当函数调用结束时,栈帧被销毁,局部变量的内存也被释放。 - 全局变量:
全局变量是在程序的顶层声明的变量,可以被整个程序中的所有函数访问。
它们通常存储在数据段(data segment)或者BSS段(未初始化的全局变量)中。这些段是程序的内存布局中专门用于存储全局变量的区域。
总体而言,局部变量的生命周期与函数调用的生命周期相关,而全局变量的生命周期与整个程序的运行时间相同。