目录
1、C/C++内存划分
C语言的动态内存管理
malloc
calloc
realloc
free
C++的动态内存管理
new和delete
operator new函数和operator delete函数
new和delete的原理
new T[N]原理
delete[]的原理
1、C/C++内存划分
1、栈:存有非静态局部变量、函数参数、返回值等。
2、内存映射段:用于装载共享的动态内存库,用户可使用系统接口创建共享内存,做进程间通信。
3、堆:用于程序运行时动态内存的分配。
4、数据段:存有全局数据和静态数据。
5、代码段:存有可执行代码、只读变量。
2、C语言的动态内存管理
C语言使用malloc、calloc、relloc、free等函数管理动态内存。
malloc
void* malloc (size_t size);
功能:向堆申请一块size字节连续可用的空间,并返回指针,
开辟成功返回指向已开辟好的空间的指针
开辟失败则返回空指针
calloc
void* calloc (size_t num, size_t size);
功能:为num个大小为size字节的元素向堆申请开辟一块空间,并且把空间的每个字节都初始化为0。
与malloc区别在于,malloc不会初始化。
realloc
void* realloc (void* ptr, size_t size);
功能:重新分配内存块,该内存块后面有足够的空间就进行原地扩容,不够就异地扩容(在堆上找另一块空间合适的连续空间使用,先将原来内存的数据拷贝到这个内存块中,在释放原来的空间)
free
void free (void* ptr);
功能:释放分配的空间。如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。如果参数ptr是NULL指针,则函数什么事都不做。
3、C++的动态内存管理
new和delete
C++兼容C语言。C语言内存管理方式虽然在C++中可以继续使用,但在有些地方并不够完善,而且使用起来比较麻烦。
因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。
new对应delete,new[]对应delete[],必须两两匹配,不匹配的话就是未定义行为。
operator new函数和operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
operator new函数功能:
1、调用malloc去分配空间,申请成功就直接返回
2、申请空间失败,就会抛出异常
operator delete函数功能:
operator delete 最终是通过free来释放空间的。
扩展(不重要):
operator new源码
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;
申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
void* p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
operator delete源码
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
void operator delete(void *pUserData)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK);
__TRY
pHead = pHdr(pUserData);
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK);
__END_TRY_FINALLY
return;
}
new和delete的原理
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:
new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申
请空间失败时会抛异常,malloc会返回NULL。
new的原理
new等价于operate new()+构造函数,先申请空间,后在申请的空间上调用构造,operate new()并不是new的重载,因为其参数没有自定义类型。
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;
申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
void* p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
由底层代码可以看出operator new是对malloc的封装。
delete原理
delete等价于operator delete()+析构函数,先调用析构,再用operator delete释放对象空间。
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
void operator delete(void *pUserData)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK);
__TRY
pHead = pHdr(pUserData);
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK);
__END_TRY_FINALLY
return;
}
由底层代码可以看出operator delete()调用了free。
针对有资源要释放的对象时,必须使用delete,free只是释放了对象的空间却没有释放对象内部的空间。
new T[N]原理
1、先调用operator new[]函数,operator new[]中实际调用operator new函数完成N个对象空间的申请。
2、再调用N次构造函数完成N个对象的初始化。
delete[]的原理
1、先调用N次析构函数,完成N个对象中资源的清理
2、再调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间