五星 C++ 内存管理

C++ 内存分区:栈、堆、全局/静态存储区、常量存储区、代码区

:存放函数的局部变量、函数参数、返回地址等,由编译器自动分配和释放

栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。

:动态申请的内存空间,就是由 **malloc **分配的内存块,由程序员控制它的分配和释放,如果程序执行结束还没有释放,操作系统会自动回收。(是可能会会释放,所以说,用完了一定记得要释放,不然会造成内存泄露)。

堆一般由程序员分配释放,若不释放,程序结束时可能由OS回收。注意这里说是可能,并非一定。所以我想再强调一次,记得要释放!注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

当内存不再使用的时候,应使用free()函数将内存块释放掉。

全局区/静态存储区(.bss 段和 .data 段):存放全局变量和静态变量,程序运行结束操作系统自动释放,在 C 语言中,未初始化的放在 .bss 段中,初始化的放在 .data 段中,C++ 中不再区分了。

解释一下静态变量

静态变量通过关键字static进行声明。

经static修饰过后的变量或者函数的作用域会发生变化。该变量存储在数据段上,可以改变变量的作用域和生命周期。

全局静态变量

在全局变量前面加上关键词static,全局变量就被定义成一个全局静态变量

(1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

(2)初始化:未经初始化的全局静态变量会被程序自动初始化为0

(3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。

局部静态变量

在局部变量前面加上关键词static,局部变量就被定义成一个局部静态变量。

(1)内存中的位置:静态存储区

(2)初始化:未经初始化的局部静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

(3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

C语言中使用静态函数的好处

(1)静态函数会被自动分配在一个一直使用的存储区,直到退出程序,避免了调用函数的压栈出栈,速度快很多。

(2)static指函数的作用域仅局限于本文件。不用担心自己定义的函数是否会与其他文件的函数同名

常量存储区(.data 段):存放的是常量,不允许修改,程序运行结束自动释放。
代码区(.text 段)存放代码,不允许修改,但可以执行。编译后的二进制文件存放在这里。
说明:

从操作系统的本身来讲,以上存储区在内存中的分布是如下形式(从低地址到高地址):

.text 段 –> .data 段 –> .bss 段 –> 堆 –> unused –> 栈 –> env

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;

/*
说明:C++ 中不再区分初始化和未初始化的全局变量、静态变量的存储区,如果非要区分下述程序标注在了括号中
*/

int g_var = 0; // g_var 在全局区(.data 段)
char *gp_var; // gp_var 在全局区(.bss 段)

int main()
{
int var; // var 在栈区
char *p_var; // p_var 在栈区
char arr[] = "abc"; // arr 为数组变量,存储在栈区;"abc"为字符串常量,存储在常量区
char *p_var1 = "123456"; // p_var1 在栈区;"123456"为字符串常量,存储在常量区
static int s_var = 0; // s_var 为静态变量,存在静态存储区(.data 段)
p_var = (char *)malloc(10); // 分配得来的 10 个字节的区域在堆区
free(p_var); // 因为使用了malloc堆的空间,由程序员自己释放掉
return 0;
}

作者:力扣 (LeetCode)
链接:https://leetcode.cn/leetbook/read/cpp-interview-highlights/e4vkxv/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。