C/C++中的内存管理小结

2020-05-12 11:57:18王冬梅

operator new

operator new在底层实现的源代码

void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc){
 // try to allocate size bytes
 void *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

operator delete在底层实现的源代码

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_FINALLY
 return;
}

从源码中能看出的是operator new和operator delete在底层也是利用malloc和free分配内存的,因此可以说new和delete不过是malloc和free的一层封装。

针对内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

针对自定义类型

1.new的原理: 调用operator new申请空间,调用构造函数完成初始化。
2.delete的原理: 调用析构函数完成清理,调用operator delete释放空间。

四:经典面试题

new | delete和malloc | free的相同点和不同点

相同点:
new、delete、malloc、free都是从堆上开辟空间,并且需要用户手动释放。

不同点:
1.new和delete是操作符,malloc和free是函数。

2.malloc申请空间不会进行初始化,new申请空间可以初始化。

3.malloc申请空间失败返回NULL,new申请空间失败会抛出异常。

4.针对自定义类型,new和delete会自动调用构造函数和析构函数处理。

五:内存泄漏

概念:内存泄漏指因为疏忽或错误造成程序已经不再使用的内存没有被释放的情况。

危害:长期运行的程序出现内存泄漏,会浪费空间,如操作系统、后台服务等等,出现内存泄漏会
导致响应越来越慢,最终卡死。

举个栗子帮助理解:

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;
}

5.1 内存泄漏的分类

堆内存泄漏