C++从内存分区到动态内存分配

C++从内存分区到动态内存分配

一.C++内存分区

C++内存分区分为五个部分:
堆,栈,自由存储区,常量存储区,静态/全局存取区。
- :new分配的内存块,程序员使用完必须自己delete,如果忘记,操作系统会在程序结束后释放该内存。
- :编译器需要时自动分配内存,常见的比如局部变量、函数参数等。
- 自由存储区:由malloc分配的内存块,和new类似,需要自己使用free释放。
- 全局/静态存储区:全局变量和静态变量,在C语言中,未初始化的全局变量是在BSS(Block Start by Symbol)区,已经初始化的全局变量在Data Segment,在C++中两者没有区别。
- 常量存储区:放置常量。

堆内存和栈内存的区别:
- 生长方向:堆内存向地址增大的方向,栈内存向地址减小的方向。
- 空间大小:堆内存一般以G为单位,而栈内存一般以M为单位。
- 分配效率:堆是由库函数提供,底层是由new/malloc,是由隐式空闲链表实现。栈计算机分配专门的寄存器放置栈地址,所以效率相比较堆要高一点。

二.malloc/new

先介绍malloc函数:与malloc函数类似的还有realloc和calloc。函数原型如下:

void *malloc(size_t size);
//分配size个字节的内存
void *realloc(void *ptr, size_t size)
//在ptr指向的区域重新分配size个字节的内存
void *calloc(size_t num, size_t size)
//分配num*size个字节的内存
void free(void *ptr);

三者分配失败直接返回空指针

底层的内存模型如下:

stack 用户栈
Mapping Area (共享库存储器映射区域)
Heap 堆
BSS (未初始化的全局变量)
data segment (已经初始化的全局变量)
code (程序文本)

动态内存器分配:
- 显示分配器:例如C/C++的malloc/free,new/delete。
- 隐式分配器:比如java的垃圾回收器。

分配器的要求:
- 能够处理任意序列;
- 实时响应:不允许重排;
- 只能使用堆;
- 块对齐;
- 不能修改已经分配的块;

底层实现:隐式空闲链表
下面介绍操作符new,new主要由三个方面:

1. new operator
2. operator new
3. placement new
  1. new operator
    这是最常见的new操作符,例如:
type *ptr = new type();
...
delete ptr;

正常的new流程就是,先申请内存,如果内存申请失败,则会抛出异常;申请成功,则调用构造函数(内置类型则不需要)。
delete则与之相反,先调用析构函数,再释放内存。
2. operator new
函数原型如下:

void *operator new(size_t);

和malloc非常类似,只分配内存,需要手动调用构造函数,
相应的operator delete也仅仅释放内存,所以在调用operator delete之前,必须手动调用析构函数。
3. placement new
这是operator new的一个重载版本,函数原型如下:

void* operator new(size_t, void* p);

placement new与operator new相比,会自动调用构造函数,operator delete之前也会自动调用析构函数。
对象模型:执行期语意

主要参考《深度探索C++对象模型》和《深入理解计算机系统》

猜你喜欢

转载自blog.csdn.net/qq_25467397/article/details/81122160