一次是忘记保存直接关机,一次是malloc开太多内存电脑起飞🛫️,刚刚tmd切换输入法给直接退出了,可以说是傻宝至极了…
不会真有人闲着无聊搞这玩意吧……
一个由C/C++编译的程序占用的内存分为以下几个部分 :
- 栈区stack:先进后出(FILO),编译器自动分配释放,存放函数的局部变量、函数参数、返回值、返回地址等。
- 堆区heap:需要手动 malloc/new 动态分配 , free/delete 释放。
- 静态区static:存储全局变量和静态变量。分为初始化数据区和未初始化数据区。
- 常量区:存放常量字符串。
- 代码区:存放函数体的二进制代码。
理论大小对比
-
栈区大小:2M或1M。
函数内申请的变量、数组,是在栈(stack)中申请的一段连续的空间。 -
静态区大小:2G.
全局变量,全局数组,静态数组(static)则是开在)。大小为2G。 -
堆区大小:视内存而定,可以开很大
malloc、new出的空间,则是开在堆(heap)的一段不连续的空间,理论上则是硬盘大小。
测试环境:win10,Visual Studio 2019:
数组最大字节数:
0
x
7
f
f
f
f
f
f
f
=
2048
M
=
2
G
0x7fffffff =2048M=2 G
0x7fffffff=2048M=2G
数组最大索引范围:
80000000
80000000
80000000 ——即int型数组最多可以
305.18
M
B
305.18MB
305.18MB
同时VS2019对于堆、栈在物理/虚拟内存中的分配设有默认设置:
虚拟内存堆分配(栈分配也是)合计大小默认1M,物理内存中堆分配(栈分配也是)合计大小默认4KB
栈区(局部变量):接近
1
M
1M
1M,250000*4=0.95367M 左右
静态区:接近2G
堆区:new出来是对象/数组,所以我们用类型不安全但是更自由的malloc直接在堆上分配内存。
结果:芜湖起飞🛫️
new与malloc的不同
- 属性
new/delete 是c++关键字,需要编译器支持;
malloc/free 是库函数,需要头文件支持,并且关键字的效率高些。 - 内存区
new操作符从自由存储区 (free store) 上为对象动态分配内存空间。
malloc函数从堆 (heap) 上动态分配内存。
自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。所有的C++编译器默认用堆来实现自由存储区,故说他们在堆/自由存储区都可。 - 大小
new不需要指定大小,自动为对象/数组分配相应大小的内存。
malloc需要指定大小sizeof(typename)*N
,并且malloc分配的内存仅仅是一块内存,具体用作变量/数组/…由你自己决定。 - 返回类型
new分配成功时返回该对象类型的指针,类型严格与对象匹配,无须类型转换,故new是符合类型安全性的操作符。
malloc分配成功时返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。 - 分配失败
new分配失败会抛出bac_alloc异常。
malloc分配失败会返回NULL。 - 自定义类型:
new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。 - 重载
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。
malloc不允许重载。
由上可知,new分配的内存在自由存储区(堆),要么是new一个对象,要么是new一个对象的数组,创造大小G以上的对象不太现实,而数组大小又限制到了2G。
故malloc来实现,总的来说,很大…具体上限未测,因为堆很大…