CC++内存管理【非常详细,对新手友好】
文章目录
- 一、程序内存划分
- 1.基础知识
- 2. 堆栈的区别
- 3. 题目练手
- 二、C语言中动态内存管理方式
- 三、C++中动态内存管理方式
- 1. new/delete操作内置类型
- 2. new/delete操作自定义类型
- 四、operator new和operator delete函数
- 1. 汇编查看编译器底层调用
- 2. 透过源码分析两个全局函数
- 五、new和delete的底层实现
- 1.内置类型
- 2.自定义类型
- 六、定位new表达式
- 1. 使用格式与使用场景
- 七、内存泄漏
- 1. 什么是内存泄漏,内存泄漏的危害
- 2. 内存泄漏分类(了解)
- 3. 如何检测内存泄漏(了解)
- 4. 如何避免内存泄漏
一、程序内存划分
1.基础知识
当我们运行一个程序时,这个程序所需要的数据及代码就会加载到内存中,不同的数据会放在内存的不同位置,内存不同位置的操作者也不同。
一般来说,一个程序所占用的内存主要分为以下几个部分:堆区、栈区、共享段库、静态区/数据段、代码段。
- 栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配栈区运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
- 堆区:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表。堆区主要进行动态内存分配,堆区的内存大小不固定,可以根据需要动态分配和释放。
- 共享段库:
- (1)文件映射[通过使用函数如mmap0或CreateFileMapping0]
- (2)动态库[包含可以被程序在运行时动态加载的代码和数据]
- (3)匿名映射[将内存映射到进程地址空间的方式,而不是映射具体的文件]
- 静态区/数据段:存放全局变量、静态数据。程序结束后由系统释放。其在程序编译时就确定了变量的存储空间大小和内存地址,具有固定的大小和位置。
- 代码段:存储**程序指令(代码)**的一块内存区域,也被称为文本段(TextSegment),代码段通常是只读的,因为程序指令一般不应该被修改,代码段中存放函数体(类成员函数和全局函数)的二进制代码。

2. 堆栈的区别
堆(Heap)与栈(Stack)是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义:
(1)程序内存布局场景下,堆与栈表示两种内存管理方式。
(2)数据结构场景下,堆与栈表示两种常用的数据结构。
我们这里讲的是程序内存布局的场景,不讲数据结构中的堆和栈。
栈简介
栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。栈的内存地址生长方向与堆相反,由高到低,(栈是向低地址方向生长的)所以后定义的变量地址低于先定义的变量。栈中存储的数据的生命周期随着函数的执行完成而结束。
int a = 10; //栈
char str[] = "str"; //栈
char *p; //栈
堆简介
堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收,分配方式类似于链表。堆的内存地址生长方向与栈相反,由低到高。(堆是向高地址方向生长的)堆中存储的数据若未释放,则其生命周期等同于程序的生命周期。
int main() {// C 中用 malloc() 函数申请char* p1 = (char *)malloc(10);// 用 free() 函数释放free(p1);// C++ 中用 new 运算符申请char* p2 = new char[10];// 用 delete 运算符释放delete[] p2;
}

3. 题目练手
刚学习了新知识我们来巩固一下,做几个题练练手。对calloc和realloc不清楚的可以先看下一节,C语言中的动态内存管理方式。

答案:


【说明】
- 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。
- 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口
创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)- 堆用于程序运行时动态内存分配,堆是可以上增长的。
- 数据段–存储全局数据和静态数据。
- 代码段–可执行的代码/只读常量
sizeof和strlen的区别:
sizeof是操作符不是函数,它是用来计算对象或者类型创建的对象所占内存空间的大小。
strlen是函数,它是用来求字符串长度的,计算的是字符串在’\0’之前出现的字符个数,如果没有看到’\0’就会继续往后找。
二、C语言中动态内存管理方式
由于本文主要讲的是C++中的动态内存管理,所以对C语言的会比较简略,如果想要深度了解,可以看看别的文章。
malloc/calloc/realloc的区别
malloc用于分配指定大小的未初始化内存块,不会对申请出来的内存做初始化工作。calloc用于分配指定数量和大小的连续内存块,并将其初始化为0。realloc用于重新分配内存块的大小,并尽可能的保留原有数据。它有两种扩容机制分别是【本地扩容】和【异地扩容】。
【本地扩容】
即在本地就有足够的空间可以扩容,此时直接在后面续上新的空间即可。
【异地扩容】
当后边没有足够的空间可以扩容时,realloc会自动找一个满足空间大小的新的连续空间。把旧空间里面的数据拷贝到新空间中,并把旧空间释放掉(无需手动释放),同时返回新空间的地址。
void Test ()
{int* p1 = (int*) malloc(sizeof(int));free(p1);// 1.malloc/calloc/realloc的区别是什么?int* p2 = (int*)calloc(4, sizeof (int));int* p3 = (int*)realloc(p2, sizeof(int)*10);// 这里需要free(p2)吗?free(p3 );
}
三、C++中动态内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
1. new/delete操作内置类型
对于C语言来说申请内存需要用malloc,释放内存需要用free,对于C++来说申请内存需要用new,释放内存需要用delete。对于普通空间来说,我们直接delete即可,但对于数组来说我们要使用delete []。
void Test()
{// 动态申请一个int类型的空间int* ptr4 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 = new int(10);// 动态申请10个int类型的空间int* ptr6 = new int[3];delete ptr4;delete ptr5;delete[] ptr6;
}

2. new/delete操作自定义类型
对于内置类型来说new,malloc与free,delete区别不大,但在自定义类型上,它们差别可就大了。它们之间最大的差别就是用new去建立一个自定义类型时,会先创建该自定义类型,然后自动调用该自定义类型的构造函数,用delete来释放一个自定义类型的时候会先调用它的析构函数,再释放内存。而malloc和free是不会自动调用构造函数和析构函数的。
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
int main()
{// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间//还会调用构造函数和析构函数cout << "malloc申请自定义类型: " << endl;A* p1 = (A*)malloc(sizeof(A));cout << "new申请自定义类型: ";A* p2 = new A(1);cout << "free释放自定义类型:" << endl;free(p1);cout << "delete释放自定义类型:";delete p2;// 内置类型是几乎是一样的cout << "内置类型基本没有差别:" << endl;int* p3 = (int*)malloc(sizeof(int)); // Cint* p4 = new int;free(p3);delete p4;cout << "malloc申请10个自定义类型: " << endl;A* p5 = (A*)malloc(sizeof(A) * 10);cout << "new申请10个自定义类型: " << endl;A* p6 = new A[10];cout << "free释放10个自定义类型" << endl;free(p5);cout << "delete释放10个自定义类型" << endl;delete[] p6;return 0;
}

【总结】
动态申请内置类型的数据:
- new/malloc、free/delete除了用法上面,没有什么本质区别。
动态申请自定义类型的数据:- new/malloc、free/delete除了用法上面,还有一个最大的区别就是在申请自定义类型的空间时,new会调》用构造函数,delete会调用析构函数,而malloc与free不会。
malloc出来的要用free释放,new出来的要用delete释放,不要混用。
四、operator new和operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数。
1. 汇编查看编译器底层调用
我们可以调用汇编来查看在使用new和delete的时候,底层到底干了什么我们不知道的事情。
A* p2 = new A(1);delete p2;
new在底层调用operator new全局函数来申请空间
- 这里我们有两个关注点,就是这两个
call指令,该指令可以用来调用函数,我们可以看到,new在底层分别调用了operator new去堆区开空间和调用A::A这个构造函数去进行初始化工作。

delete在底层调用operator delete全局函数来释放空间 - 同理我们这里也有两个关注点就是这两个
call指令,进行了两次函数调用,第一次是先调用A::~A析构函数来进行自定义类型的清理工作,然后再调用operator delete释放从堆区申请的资源。

2. 透过源码分析两个全局函数
operator new,通过查看它的源码我们可以发现,它内部还是使用【malloc】去堆区申请空间的。
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytesvoid* p;while ((p = malloc(size)) == 0)if (_callnewh(size) == 0){// report no memory// 如果申请内存失败了,这里会抛出bad_alloc 类型异常static const std::bad_alloc nomem;_RAISE(nomem);}return (p);
}
operator delete,仔细观察我们可以发现这段代码调用了一个_free_dbg的函数,其实这个函数就是C语言中的【free】,那么可以得出结论就是operator delete类似是调用了【delete】来进行释放空间的。
/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void* pUserData)
{_CrtMemBlockHeader* pHead;RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));if (pUserData == NULL)return;_mlock(_HEAP_LOCK); /* block other threads */__TRY/* get a pointer to memory block header */pHead = pHdr(pUserData);/* verify block type */_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));_free_dbg(pUserData, pHead->nBlockUse);__FINALLY_munlock(_HEAP_LOCK); /* release other threads */__END_TRY_FINALLYreturn;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
拓展
那既然这俩全局函数底层就是【malloc】和【free】的话,那岂不是我们可以直接使用operator new和operator delete来进行替代呢?
准确来说是这样的,例如以下程序我们将mallloc和free用两个全局函数替换然后运行发现,效果等同于【malloc】和【free】。
int main(void)
{int* p1 = (int*)operator new(sizeof(int));int* p2 = new int;operator delete(p1);delete p2;A* a1 = (A*)operator new(sizeof(A));A* a2 = new A(1);operator delete(a1);delete a2;return 0;
}
五、new和delete的底层实现
1.内置类型
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
2.自定义类型
new的原理:
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
delete的原理:
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
new T[N]的原理
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
- 在申请的空间上执行N次构造函数
delete[]的原理
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间
六、定位new表达式
1. 使用格式与使用场景
【概念】:定位new表达式是C++中的一种内存分配方式,它允许在特定的内存位置上创建对象。它与常规的new表达式不同,常规的new表达式会自动分配内存,并返回指向新分配内存的指针
【使用格式】:
new (place_address) type
//或
new (place_address) type(initializer-list)
//place_address必须是一个指针
//initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
// 定位new/replacement new
int main()
{// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行A* p1 = (A*)malloc(sizeof(A));new(p1)A;// 注意:如果A类的构造函数有参数时,此处需要传参p1->~A();free(p1);A* p2 = (A*)operator new(sizeof(A));new(p2)A(10);p2->~A();operator delete(p2);return 0;
}
七、内存泄漏
1. 什么是内存泄漏,内存泄漏的危害
什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
void MemoryLeaks()
{// 1.内存申请了忘记释放int* p1 = (int*)malloc(sizeof(int));int* p2 = new int;// 2.异常安全问题int* p3 = new int[10];Func(); // 这里Func函数抛异常导致 delete[] p3未执行,p3没被释放.delete[] p3;
}
2. 内存泄漏分类(了解)
C/C++程序中一般我们关心两种方面的内存泄漏:
- 堆内存泄漏(Heap leak)
堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。 - 系统资源泄漏
指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。
3. 如何检测内存泄漏(了解)
在vs下,可以使用windows操作系统提供的_CrtDumpMemoryLeaks() 函数进行简单检测,该函数只报出了大概泄漏了多少个字节,没有其他更准确的位置信息。
int main()
{int* p = new int[10];// 将该函数放在main函数之后,每次程序退出的时候就会检测是否存在内存泄漏_CrtDumpMemoryLeaks();return 0;
}
// 程序退出后,在输出窗口中可以检测到泄漏了多少字节,但是没有具体的位置
Detected memory leaks!
Dumping objects ->
{79} normal block at 0x00EC5FB8, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
因此写代码时一定要小心,尤其是动态内存操作时,一定要记着释放。但有些情况下总是防不胜防,简单的可以采用上述方式快速定位下。如果工程比较大,内存泄漏位置比较多,不太好查时一般都是借助第三方内存泄漏检测工具处理的。
- 在linux下内存泄漏检测:在linux下内存泄漏检测
- 在windows下使用第三方工具:VLD工具说明
- 其他工具:内存泄漏工具比较
4. 如何避免内存泄漏
- 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。ps:这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智能指针来管理才有保证。
- 采用RAII思想或者智能指针来管理资源。
- 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
- 出问题了使用内存泄漏工具检测。ps:不过很多工具都不够靠谱,或者收费昂贵。
总结一下:
内存泄漏非常常见,解决方案分为两种:1、事前预防型。如智能指针等。2、事后查错型。如泄漏检测工具。
相关文章:
CC++内存管理【非常详细,对新手友好】
文章目录 一、程序内存划分1.基础知识2. 堆栈的区别3. 题目练手 二、C语言中动态内存管理方式三、C中动态内存管理方式1. new/delete操作内置类型2. new/delete操作自定义类型 四、operator new和operator delete函数1. 汇编查看编译器底层调用2. 透过源码分析两个全局函数 五、…...
022-安全开发-PHP应用留言板功能超全局变量数据库操作第三方插件引用
022-安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用 #知识点: 1、PHP留言板前后端功能实现 2、数据库创建&架构&增删改查 3、内置超全局变量&HTML&JS混编 4、第三方应用插件&传参&对象调用 演示案例&a…...
大白话解析LevelDB 3: SST Compaction
SST Compaction 文章目录 SST Compaction什么是Compact SST什么时候触发Compact SST第一处 读取 Key 的时候第二处 使用迭代器遍历数据库时第三处 写入 Key 时第四处 刚打开数据库时 如何进行Compact SST计算Compaction范围进行Compaction创建一个迭代器用于读取Compaction范围…...
【Python】02快速上手爬虫案例二:搞定验证码
文章目录 前言1、不要相信什么验证码的库2、以古诗文网为例,获取验证码1)code_result.py2)gsw.py 前言 提示:以古诗文网为例,获取验证码: 登录:https://so.gushiwen.cn/user/login.aspx 1、不…...
C# 中的接口
简介 官方说明:接口定义协定。 实现该协定的任何 class 或 struct 必须提供接口中定义的成员的实现。 接口可为成员定义默认实现。 它还可以定义 static 成员,以便提供常见功能的单个实现。 从 C# 11 开始,接口可以定义 static abstract 或 …...
一篇文章带你了解C++中隐含的this指针
文章目录 一、this指针的引出二、this指针的特性【面试题】 一、this指针的引出 我们先来定义一个日期类Date,下面这段代码执行的结果是什么呢? class Date { public:void Init(int year, int month, int day){_year year;_month month;_day day;}v…...
shardinig-JDBC二开-支持sharding-jdbc的配置文件接入到nacos
代码在 https://gitee.com/lbmb/mb-live-app 中 【mb-live-framework】 模块里面的【mb-live-framework-datasource-stater】 如果喜欢 希望大家给给star 项目还在持续更新中。 背景介绍: 因为近期在自己写一套直播项目。使用到了sharding-jdbc来做分库分表的组件…...
a-table自定义展开图标
原文来自:vue 修改ant中table表格的展开图标 树形表格expandIcon自定义图标 <template #expandIcon"props"><span v-if"props.record.children?.length > 0"><divv-if"props.expanded"style"display: inline…...
Kubernetes Ingress暴露应用的工作流程
文章目录 一、Igress是什么二、安装Igress Controller三、Service NodePort模式暴露Ingress Controller四、创建ingress 进行访问查看ingress controller生成的规则(两种类型通用) 五、HostNetwork模式暴露Ingress Controller总结: 一、Igress是什么 一般负载均衡器…...
Redis应用(1)缓存(1.2)------Redis三种缓存问题
三者出现的根本原因是:Redis缓存命中率下降,请求直接打到DB上了。 一、 缓存穿透: 1、定义: 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。…...
安全 专题
[实践总结] 日志注入问题(log4j2) [实践总结] Java 防止SQL注入的四种方案 [实践总结] 如何防护 order by 导致的SQL注入 [实践总结] 限制正则表达式匹配次数/时间 防止DoS攻击 [实践总结] java XML解析防止外部实体注入 [Ref] yaml.load的漏洞利用…...
自然语言处理-文本对分类或回归
我们研究了自然语言推断。它属于文本对分类,这是一种对文本进行分类的应用类型。 以一对文本作为输入但输出连续值,语义文本相似度是一个流行的“文本对回归”任务。 这项任务评估句子的语义相似度。例如,在语义文本相似度基准数据集&#x…...
以梦为码,CodeArts Snap 缩短我与算法的距离
背景 最近一直在体验华为云的 CodeArts Snap,逐渐掌握了使用方法,代码自动生成的准确程度大大提高了。 自从上次跟着 CodeArts Snap 学习用 Python 编程,逐渐喜欢上了 Python。 我还给 CodeArts Snap 起了一个花名: 最佳智能学…...
SpringMVC-HttpMessageConverter 报文信息转化器
文章目录 HttpMessageConverter一、概念二、RequestBody三、RequestEntity四、 ResponseBody1.返回JSON格式的字符串 五、RestController六、ResponseEntity HttpMessageConverter 一、概念 报文信息转化器,将请求报文转化为Java对象,或将Java对象转化…...
[AG32VF407]国产MCU+FPGA 使用I2C测试陀螺仪MPU6050
视频讲解 [AG32VF407]国产MCUFPGA 使用I2C测试陀螺仪MPU6050 实验过程 查看原理图中定义的I2C的管脚,PB0和PB1 在board.ve中定义的引脚功能 I2C0_SDA PIN_36 I2C0_SCL PIN_35新建工程 测试代码 #include "board.h"#define MIN_IRQ_PRIORITY 1 #define …...
ES 可扩展、高可靠、使用场景等常见问题
ElasticSearch的常见问题 什么是ElasticSearch ElasticSearch是一款非常强大的、基于Lucene的开源搜索及分析引擎;它是一个实时的分布式搜索分析引擎,它能让你以前所未有的速度和规模,去探索你的数据。 它被用作全文检索、结构化搜索、分析…...
<网络安全>《4 网络安全产品之web应用防护系统》
1 基本概念 1.1 WAF Web应用防护系统(也称为:网站应用级入侵防御系统。英文:Web Application Firewall,简称:WAF)。一般作为网关设备,防护Web、Webmail服务器等。 1.2 本质 WAF的本质是Web应…...
如何解决Flutter应用程序的兼容性问题
随着移动应用开发领域的不断发展,Flutter作为一种跨平台框架,受到了越来越多开发者的青睐。要确保Flutter应用程序能够在不同的设备和操作系统上稳定运行,并提供一致的用户体验,我们需要重视应用程序的兼容性问题。下面将简单的介…...
详解Mockito
详解Mockito 1. Mockito简介 在我们的编程世界中,测试是一个非常重要的环节,它能帮助我们确保代码的质量和稳定性。而在众多的测试方法中,Mock测试是一种非常有效的手段。 1.1 什么是 Mock 测试 Mock测试,顾名思义,…...
【论文+App试玩+图像到视频】2311.Animate-anyone:上传1张图片为任何人制作动画(用于角色动画的一致且可控的图像到视频合成)(暂未开源)
项目主页:https://humanaigc.github.io/animate-anyone/ 论文: Animate Anyone: Consistent and Controllable Image-to-Video Synthesis for Character Animation 摩尔线程复现代码:https://github.com/MooreThreads/Moore-AnimateAnyone 摩尔windows一…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
