malloc/free和new/delete的区别
malloc/free
和new/delete
的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:
malloc
和free
是函数,new
和delete
是操作符- malloc申请的空间不会初始化,new可以初始化
- malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
- malloc的返回值为
void*
, 在使用时必须强转,new不需要,因为new后跟的是空间的类型 - malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
- 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
new/delete
比malloc和free的效率稍微低点,因为new/delete的底层封装了malloc/free
请设计一个类,该类只能在堆上创建对象
- 构造函数私有化
- 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
- 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
class HeapOnly { public: static HeapOnly* CreateObject() { return new HeapOnly; } private: HeapOnly() {} // C++98 // 1.只声明,不实现。因为实现可能会很麻烦,而你本身不需要 // 2.声明成私有 HeapOnly(const HeapOnly&);
};
- c++11中提供delete
HeapOnly(const HeapOnly&) = delete;
请设计一个类,该类不能在栈上创建对象
class StackOnly
{
public: static StackOnly CreateObject() { return StackOnly(); } private: StackOnly() {}
};
只能在栈上创建对象,即不能在堆上创建
因此只要将new的功能屏蔽掉即可,即屏蔽掉operator new和定 位new表达式,注意:屏蔽了operator new,实际也将定位new屏蔽掉。
class StackOnly
{
public: StackOnly() {} private: void* operator new(size_t size); void operator delete(void* p); };
检测下面程序运行结果
class Test
{
public:~Test(){delete this;}};int main()
{Test* pt = new Test;delete pt;return 0;
}
答:无限递归,每回在释放对象时delete this
,this
又是对象,又要调用析构,所以无限递归。
如何一次在堆上申请4G的内存?
在探讨这个问题之前,我们需要认识到机器的内存分布。
因为Windows下的机器内存分布模型我们不清楚。所以我们在这里讨论的是Linux下的4G内存空间的申请。
假如我们现在的Linux一共有4G的内存空间。那么它有1G是供操作系统内核使用的。也就是说我们程序最多只能申请到3G的空间,事实上,我们最大申请到的空间也就2G左右。
#include<iostream>
using namespace std;
int main()
{void* p = new char[0xfffffffful];cout << "new:" << p << endl;return 0;}
上述代码按64位编译就可以申请了
不要疑问4G*4G
空间,我们知道虚拟地址空间和物理地址空间之间有一种映射关系,我们能申请到并不意味着物理地址真的有这么大。你想,我们申请到的4G空间并不是说需要一下子需要这么大,只是说可以满足我们4G的需求就可以了,所以当你用到的地方才会真的申请空间,一旦哪一部分释放空间了,就会把前边释放的空间再拿过来用(读者可以想象这个过程)。
内存泄露
什么是内存泄露
内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上 的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪 费。
内存泄露分类
- 堆内存泄露
堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存, 用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那 么以后这部分空间将无法再被使用,就会产生Heap Leak - 系统资源泄漏
指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统 资源的浪费,严重可导致系统效能减少,系统执行不稳定。
如何解决
- Linux下有相应的工具进行检测
- windows下有第三方工具进行检测
- 其他工具
如何避免
- 事前预防,如c++中智能指针
- 事后查错,如检错工具