C/C++中的内存分区
内存影像区 | 内容 | 权限 |
栈区 | 函数中的普通变量、局部变量、函数、参数和返回地址 | 可读可写 |
堆区 | 动态申请的内存 | 可读可写 |
(全局)静态变量区 | Static修饰的变量 | 可读可写 |
常量区 | 用于初始化变量的常量 | 只读 |
代码区 | 代码指令 | 只读 |
高地址 低地址 | 栈区(向下增长)stack | 由编译器自动分配释放,存放局部变量、形参、返回值 |
堆区(向上增长)heep | 由程序员分配内存和释放 | |
全局(静态)区 | 未初始化全局/静态区 | |
已初始化全局/静态区 | ||
常量区 | 字符串“ABCD” | |
代码区 | 存放程序的代码 |
C、C++中内存分配方式可以分为三种:
(1)从静态存储区域分配:
内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。
(2)在栈上分配:
在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配:
即动态内存分配。程序在运行的时候用 malloc 或 new 申请任意大小的内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。
一个C、C++程序编译时内存分为 5 大存储区:堆区、栈区、全局区、文字常量区、程序代码区。
代码区(Text Segment):
这个区域存储了程序的机器指令,即CPU要执行的代码。
代码区通常是只读的,以防止程序意外地修改自己的指令。
当程序被加载到内存中时,代码区的内容从可执行文件中复制而来。
全局/静态数据区(Data Segment):
全局/静态数据区包含了全局变量、静态变量和常量数据。
全局变量和静态变量在程序的整个生命周期内都存在,而常量数据则用于存储字符串常量等不变的值。
这个区域在程序开始执行前就被初始化,并在程序结束时被释放。
它分为已初始化和未初始化两个部分:
已初始化数据区(Data Segment):存储已初始化的全局变量和静态变量。
未初始化数据区(BSS Segment):存储未初始化的全局变量和静态变量,这些变量在程序开始执行前被自动初始化为零。
堆区(Heap):
堆区用于动态内存分配。
程序员可以使用如malloc、calloc、realloc等函数在堆上分配内存,并使用free函数释放内存。
堆区的大小在程序运行时是可变的,由程序员控制。
如果程序员忘记释放已分配的内存,可能会导致内存泄漏。
栈区(Stack):
栈区用于存储局部变量和函数调用信息(如函数参数、返回值地址、局部变量指针等)。
栈的大小在程序编译时确定,并在程序运行时由系统自动管理。
每当函数被调用时,系统会在栈上为该函数的局部变量和调用信息分配空间;当函数返回时,这些空间会被自动释放。
栈的访问速度非常快,因为栈内存通常是连续分配的。
这些内存分区共同构成了C语言程序的内存布局。程序员需要了解这些分区的特性和用途,以便正确地管理内存和编写高效的C语言程序。同时,也要注意避免内存泄漏、缓冲区溢出等常见的内存管理错误。