一丶C/C++的内存分布
- 栈区(Stack):用于存放函数内的局部变量、形参和函数返回值。它是一块连续的空间,由编译器在需要时自动分配,并在函数执行结束时自动释放。栈的特点是先进后出(FILO),其地址是从高地址向低地址增长。
- 堆区(Heap):用于存放程序运行时动态分配的内存。程序员通过malloc、calloc或new等函数主动申请内存,并通过free或delete等函数释放内存。如果程序员忘记释放,程序结束时操作系统会回收这部分内存。堆是从低地址向高地址增长。
- 全局/静态区(Static):存放全局变量和静态变量,包括初始化和未初始化的。这部分内存在程序的整个生命周期内都是存在的,直到程序结束才会被系统释放。全局区又分为已初始化全局区(data)和未初始化全局区(bss)。
- 常量区(Constant):存放常量数据,如常量字符串等。这部分内存在程序结束后由系统释放。
- 代码区(Code):存放程序的二进制代码,包括函数体和其他可执行代码。这部分内存是只读的,程序结束后由系统释放。
二丶C/C++的内存管理方式
1.C语言:malloc/calloc/realloc/free
2.C++:new 和 delete
(1.内置类型使用new和delete,申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[]。
void test()
{
int* ptr1 = new int; //申请一个int*类型的空间
int* ptr2 = new int(1); //申请一个int*的空间并初始化为1
int* ptr3 = new int[10]; //动态申请10个int*类型的空间
delete ptr1;
delete ptr2;
delete []ptr3;
}
(2.自定义类型使用
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与 free不会。
3.operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是 系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
源码看不懂没关系,只需要知道,operator new 实际也是通过malloc来申请空间,如果 malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施 就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
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: 该函数最终是通过free来释放空间的
*/
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;
}
4.new和delete的实现原理
new
和delete
是C++中用于动态内存管理的运算符,它们的实现原理涉及以下几个关键步骤:
-
分配内存:当使用
new
创建一个对象时,底层会调用operator new
函数来申请内存空间。这个函数负责在堆上分配足够的内存来存储对象的数据成员以及可能的额外开销(如对齐填充或内部数据结构的维护)。 -
调用构造函数:一旦内存被分配,
new
操作符会调用对象的构造函数来初始化对象的状态。 -
释放内存:当使用
delete
销毁一个对象时,底层会调用operator delete
函数来释放之前由new
操作符分配的内存空间。这个函数负责将之前分配的内存标记为可用,以便未来重用。 -
调用析构函数:在释放内存之前,
delete
操作符会先调用对象的析构函数来执行必要的清理工作。
需要注意的是,如果自定义了类的operator new
和operator delete
,那么在使用new
和delete
操作符时,会优先调用这些自定义的版本。如果没有自定义,则会使用标准库提供的全局函数版本。
new T[N]的原理
1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对 象空间的申请
2. 在申请的空间上执行N次构造函数
delete[]的原理
1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释 放空间