目录
- 引言
- [1. 内存分布](#1. 内存分布)
- 2.C动态内存管理方式:malloc/calloc/realloc/free
- [3. C++动态内存管理:new和delete](#3. C++动态内存管理:new和delete)
-
- 3.1内置类型
- [3.2 自定义类型](#3.2 自定义类型)
- [4.operator new与operator delete函数](#4.operator new与operator delete函数)
-
- [4.1 operator new 与operator delete函数](#4.1 operator new 与operator delete函数)
- [5. new和delete的实现底层](#5. new和delete的实现底层)
-
- [5.1 内置类型](#5.1 内置类型)
- [5.2 自定义类型](#5.2 自定义类型)
引言
什么是内存管理?以下便是一些内存管理的基础概念
1.内存分配(Memory Allocation): 内存分配是指操作系统或应用程序为程序执行和数据存储分配内存空间的过程。这可以通过动态分配和静态分配来实现。
静态分配: 在程序运行之前,编译器为程序的变量和数据分配固定的内存空间。这些分配在程序执行期间保持不变。
动态分配: 在程序运行时,使用动态内存分配函数(例如C++中的new和delete、C语言中的malloc和free)从堆中分配内存。这使得程序能够在运行时根据需要分配和释放内存。
2.内存释放(Memory Deallocation): 已分配的内存需要在不再需要的时候释放,以防止内存泄漏。动态内存分配后,需要负责释放这些内存。
3.碎片(Fragmentation): 内存碎片分为两类:外部碎片和内部碎片。外部碎片是指未分配的零散内存块,而内部碎片是指已分配内存块中未被使用的部分。
4.虚拟内存(Virtual Memory): 操作系统使用虚拟内存技术,允许程序使用比实际物理内存更大的内存空间。这通过将部分数据和代码存储在硬盘上的交换文件中来实现。
5.页表(Page Tables): 用于将虚拟地址映射到物理地址。页表允许操作系统在虚拟内存和物理内存之间进行映射。
6.内存保护: 操作系统通过设置合适的权限和访问规则,确保程序不能越权地访问其他程序或操作系统的内存空间。
7.内存管理单元(Memory Management Unit,MMU): 是计算机硬件的一部分,负责虚拟地址和物理地址之间的转换,以及内存访问的权限控制。
1. 内存分布
- 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
- 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口
创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下) - 堆用于程序运行时动态内存分配,堆是可以上增长的。
- 数据段--存储全局数据和静态数据。
- 代码段--可执行的代码/只读常量。
2.C动态内存管理方式:malloc/calloc/realloc/free
他们的区别:
malloc:动态开辟,分配空间不初始化
calloc:分配空间并初始化为0
realloc:重新分配内存块
c
#include<stdlib.h>
int main()
{
int* p1 = (int*)malloc(sizeof(int));
*p1 = 2;
int* p2 = (int*)calloc(4, sizeof(int));
int* p3 = (int*)realloc(p2, sizeof(int) * 2);
free(p1);
free(p3);
return 0;
}
malloc的实现原理:
glibc中malloc实现原理
3. C++动态内存管理:new和delete
3.1内置类型
cpp
int main()
{
//动态申请一个int类型
int* p1 = new int;
//动态申请一个int类型并初始化为10
int* p2 = new int(10);
//动态申请int数组
int* p3 = new int[10];
delete p1;
delete p2;
delete[] p3;
}
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[],注意:匹配起来使用
3.2 自定义类型
cpp
class A
{
private:
int _a;
public:
A(int a=2) :_a(a)
{
cout << "A" << endl;
}
~A()
{
cout << "~A" << endl;
}
};
int main()
{
A* p1 = new A;
delete p1;
A* p2 = new A[10];
delete[] p2;
return 0;
}
注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数
4.operator new与operator delete函数
4.1 operator new 与operator delete函数
operator new和operator delete 是 C++ 中用于动态分配内存和释放的函数。它是 C++ 中的运算符重载函数,用于在堆(heap)上动态分配内存存空间,并返回分配的内存地址。
在 C++ 中,当你需要动态分配内存时,你可以使用 new 运算符。new 运算符背后实际上调用了 operator new 函数来执行内存分配操作。
new和delete是用户进行动态内存申请和释放的操作符,而operator new和operator delete是系统提供的函数,new在底层调用operator new 全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间
5. new和delete的实现底层
5.1 内置类型
前面已经提到过内置类型的应用
申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间 ,new[]和delete[]申请的是连续空间 ,而且new在申
请空间失败时会抛异常 ,malloc会返回NULL。
5.2 自定义类型
new的原理
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
delete的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
new T[N]的原理
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
- 在申请的空间上执行N次构造函数
delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间